From 86ef11c52109381a5cdcc1106723df153cab387f Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Wed, 9 Aug 2023 18:33:59 +0300 Subject: [PATCH] Now viewport_id always will be in a ViewportId you cannot create a ViewportId you can only get the main one everywere or get the current viewport id with `Context::get_viewport_id` --- Cargo.lock | 1 + crates/eframe/src/lib.rs | 10 +- crates/eframe/src/native/epi_integration.rs | 21 +- crates/eframe/src/native/run.rs | 161 ++-- crates/egui-wgpu/Cargo.toml | 1 + crates/egui-wgpu/src/winit.rs | 15 +- crates/egui-winit/src/lib.rs | 8 +- crates/egui/src/containers/window.rs | 857 +++++++++--------- crates/egui/src/context.rs | 135 +-- crates/egui/src/data/output.rs | 12 +- crates/egui/src/lib.rs | 26 +- crates/egui/src/memory.rs | 18 +- crates/egui/src/viewport.rs | 25 +- .../egui_demo_app/src/apps/custom3d_glow.rs | 2 +- crates/egui_demo_app/src/wrap_app.rs | 10 +- crates/egui_demo_lib/benches/benchmark.rs | 77 +- crates/egui_demo_lib/src/lib.rs | 23 +- examples/confirm_exit/src/main.rs | 2 +- examples/custom_3d_glow/src/main.rs | 2 +- examples/custom_font/src/main.rs | 2 +- examples/custom_font_style/src/main.rs | 2 +- examples/custom_window_frame/src/main.rs | 2 +- examples/download_image/src/main.rs | 2 +- examples/file_dialog/src/main.rs | 2 +- examples/hello_world/src/main.rs | 2 +- examples/hello_world_par/src/main.rs | 2 +- examples/keyboard_events/src/main.rs | 2 +- examples/puffin_profiler/src/main.rs | 2 +- examples/retained_image/src/main.rs | 2 +- examples/screenshot/src/main.rs | 2 +- examples/serial_windows/src/main.rs | 2 +- examples/svg/src/main.rs | 2 +- examples/user_attention/src/main.rs | 2 +- examples/viewports/src/main.rs | 4 +- 34 files changed, 775 insertions(+), 663 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78f414bb7..62d1d4b71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1195,6 +1195,7 @@ version = "0.22.0" dependencies = [ "bytemuck", "document-features", + "egui", "epaint", "log", "puffin", diff --git a/crates/eframe/src/lib.rs b/crates/eframe/src/lib.rs index 46d2c225d..147650482 100644 --- a/crates/eframe/src/lib.rs +++ b/crates/eframe/src/lib.rs @@ -269,6 +269,8 @@ pub fn run_simple_native( native_options: NativeOptions, update_fun: impl FnMut(&egui::Context, &mut Frame) + 'static, ) -> Result<()> { + use egui::{ViewportId, ViewportRender}; + struct SimpleApp { update_fun: U, } @@ -277,12 +279,12 @@ pub fn run_simple_native( &mut self, ctx: &egui::Context, frame: &mut Frame, - render_function: Option<&(dyn Fn(&egui::Context, u64, u64) + Send + Sync)>, + render: Option<&ViewportRender>, ) { - if ctx.get_viewport_id() == 0 { + if ctx.get_viewport_id() == ViewportId::MAIN { (self.update_fun)(ctx, frame); - } else if let Some(render_function) = render_function { - render_function(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()) + } else if let Some(render_function) = render { + render_function(ctx) } } } diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 9483ebae4..4c83ec15b 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -9,7 +9,7 @@ use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; #[cfg(feature = "accesskit")] use egui::accesskit; -use egui::{Context, NumExt as _, ViewportBuilder}; +use egui::{Context, NumExt as _, ViewportBuilder, ViewportId, ViewportRender}; #[cfg(feature = "accesskit")] use egui_winit::accesskit_winit; use egui_winit::{native_pixels_per_point, EventResponse, WindowSettings}; @@ -432,7 +432,14 @@ impl EpiIntegration { let saved_memory: egui::Memory = self.egui_ctx.memory(|mem| mem.clone()); self.egui_ctx .memory_mut(|mem| mem.set_everything_is_visible(true)); - let full_output = self.update(app, window, egui_winit, None, 0, 0); + let full_output = self.update( + app, + window, + egui_winit, + None, + ViewportId::MAIN, + ViewportId::MAIN, + ); self.pending_full_output.append(full_output); // Handle it next frame self.egui_ctx.memory_mut(|mem| *mem = saved_memory); // We don't want to remember that windows were huge. self.egui_ctx.clear_animations(); @@ -449,14 +456,14 @@ impl EpiIntegration { event: &winit::event::WindowEvent<'_>, window_id: &winit::window::WindowId, egui_winit: &mut egui_winit::State, - viewport_id: u64, + viewport_id: ViewportId, ) -> EventResponse { use winit::event::{ElementState, MouseButton, WindowEvent}; match event { WindowEvent::CloseRequested => { log::debug!("Received WindowEvent::CloseRequested"); - self.close = app.on_close_event() && viewport_id == 0; + self.close = app.on_close_event() && viewport_id == ViewportId::MAIN; log::debug!("App::on_close_event returned {}", self.close); } WindowEvent::Destroyed => { @@ -497,9 +504,9 @@ impl EpiIntegration { app: &mut dyn epi::App, window: &winit::window::Window, egui_winit: &mut egui_winit::State, - render: Option>>, - viewport_id: u64, - parent_id: u64, + render: Option>>, + viewport_id: egui::ViewportId, + parent_id: egui::ViewportId, ) -> egui::FullOutput { let frame_start = std::time::Instant::now(); diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 785f4a6d6..85008de85 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -3,7 +3,7 @@ use std::{sync::Arc, time::Instant}; -use egui::{epaint::ahash::HashMap, mutex::RwLock, ViewportBuilder}; +use egui::{epaint::ahash::HashMap, mutex::RwLock, ViewportBuilder, ViewportId}; use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; use winit::{ event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget}, @@ -23,7 +23,7 @@ use super::epi_integration::{self, load_icon, EpiIntegration}; #[derive(Debug)] pub enum UserEvent { RequestRepaint { - window_id: u64, + id: ViewportId, when: Instant, /// What the frame number was when the repaint was _requested_. frame_nr: u64, @@ -79,8 +79,8 @@ trait WinitApp { window_id: winit::window::WindowId, ) -> Option>>; - fn get_window_winit_id(&self, id: u64) -> Option; - fn get_window_id(&self, id: &winit::window::WindowId) -> Option; + fn get_window_winit_id(&self, id: ViewportId) -> Option; + fn get_window_id(&self, id: &winit::window::WindowId) -> Option; fn save_and_destroy(&mut self); @@ -168,7 +168,7 @@ fn run_and_return( winit::event::Event::UserEvent(UserEvent::RequestRepaint { when, frame_nr, - window_id, + id: window_id, }) => { if winit_app.frame_nr() == *frame_nr { log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}"); @@ -325,7 +325,7 @@ fn run_and_exit(event_loop: EventLoop, mut winit_app: impl WinitApp + winit::event::Event::UserEvent(UserEvent::RequestRepaint { when, frame_nr, - window_id, + id: window_id, }) => { if winit_app.frame_nr() == frame_nr { if let Some(window_id) = winit_app.get_window_winit_id(window_id) { @@ -462,8 +462,8 @@ mod glow_integration { builder: ViewportBuilder, gl_surface: Option>, window: Option>>, - window_id: u64, - parent_id: u64, + window_id: ViewportId, + parent_id: ViewportId, render: Option>>, pub egui_winit: Option, } @@ -487,11 +487,13 @@ mod glow_integration { current_gl_context: Option, not_current_gl_context: Option, - windows: HashMap>>, - window_maps: HashMap, + windows: HashMap>>, + window_maps: HashMap, } + #[allow(unsafe_code)] unsafe impl Sync for GlutinWindowContext {} + #[allow(unsafe_code)] unsafe impl Send for GlutinWindowContext {} impl GlutinWindowContext { @@ -599,20 +601,20 @@ mod glow_integration { let mut window_maps = HashMap::default(); if let Some(window) = &window { - window_maps.insert(window.id(), 0); + window_maps.insert(window.id(), ViewportId::MAIN); } let mut windows = HashMap::default(); windows.insert( - 0, + ViewportId::MAIN, Arc::new(RwLock::new(Window { builder: window_builder, gl_surface: None, window: window.map(|w| Arc::new(RwLock::new(w))), - window_id: 0, + window_id: ViewportId::MAIN, egui_winit: None, render: None, - parent_id: 0, + parent_id: ViewportId::MAIN, })), ); @@ -739,18 +741,22 @@ mod glow_integration { Ok(()) } - fn window(&self, window_id: u64) -> Arc> { + fn window(&self, viewport_id: ViewportId) -> Arc> { self.windows - .get(&window_id) + .get(&viewport_id) .map(|w| w.clone()) .expect("winit window doesn't exist") } - fn resize(&mut self, window_id: u64, physical_size: winit::dpi::PhysicalSize) { + fn resize( + &mut self, + viewport_id: ViewportId, + physical_size: winit::dpi::PhysicalSize, + ) { let width = std::num::NonZeroU32::new(physical_size.width.at_least(1)).unwrap(); let height = std::num::NonZeroU32::new(physical_size.height.at_least(1)).unwrap(); - if let Some(window) = self.windows.get(&window_id) { + if let Some(window) = self.windows.get(&viewport_id) { let mut window = window.write(); if let Some(gl_surface) = &window.gl_surface { self.current_gl_context = Some( @@ -788,7 +794,7 @@ mod glow_integration { // re-initializing the `GlowWinitRunning` state on Android if the application // suspends and resumes. app_creator: Option, - is_focused: Arc>>, + is_focused: Arc>>, } impl GlowWinitApp { @@ -804,7 +810,7 @@ mod glow_integration { native_options, running: Arc::new(RwLock::new(None)), app_creator: Some(app_creator), - is_focused: Arc::new(RwLock::new(Some(0))), + is_focused: Arc::new(RwLock::new(Some(ViewportId::MAIN))), } } @@ -826,7 +832,7 @@ mod glow_integration { }; glutin_window_context.on_resume(event_loop)?; - if let Some(window) = &glutin_window_context.windows.get(&0) { + if let Some(window) = &glutin_window_context.windows.get(&ViewportId::MAIN) { let window = window.read(); if let Some(window) = &window.window { epi_integration::apply_native_options_to_window(&window.read(), native_options); @@ -866,13 +872,25 @@ mod glow_integration { .unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error)); let system_theme = system_theme( - &gl_window.window(0).read().window.as_ref().unwrap().read(), + &gl_window + .window(ViewportId::MAIN) + .read() + .window + .as_ref() + .unwrap() + .read(), &self.native_options, ); let mut integration = epi_integration::EpiIntegration::new( event_loop, painter.max_texture_side(), - &gl_window.window(0).read().window.as_ref().unwrap().read(), + &gl_window + .window(ViewportId::MAIN) + .read() + .window + .as_ref() + .unwrap() + .read(), system_theme, &self.app_name, &self.native_options, @@ -883,7 +901,7 @@ mod glow_integration { ); #[cfg(feature = "accesskit")] { - let window = gl_window.windows.get(&0).unwrap(); + let window = gl_window.windows.get(&ViewportId::MAIN).unwrap(); let window = &mut *window.write(); integration.init_accesskit( window.egui_winit.as_mut().unwrap(), @@ -901,7 +919,7 @@ mod glow_integration { integration.egui_ctx.set_desktop(true); gl_window - .window(0) + .window(ViewportId::MAIN) .read() .window .as_ref() @@ -910,7 +928,7 @@ mod glow_integration { .set_ime_allowed(true); if self.native_options.mouse_passthrough { gl_window - .window(0) + .window(ViewportId::MAIN) .read() .window .as_ref() @@ -931,7 +949,7 @@ mod glow_integration { event_loop_proxy .lock() .send_event(UserEvent::RequestRepaint { - window_id: info.window_id, + id: info.viewport_id, when, frame_nr, }) @@ -943,7 +961,7 @@ mod glow_integration { .expect("Single-use AppCreator has unexpectedly already been taken"); let mut app; { - let window = gl_window.window(0); + let window = gl_window.window(ViewportId::MAIN); let window = &mut *window.write(); app = app_creator(&epi::CreationContext { egui_ctx: integration.egui_ctx.clone(), @@ -995,7 +1013,7 @@ mod glow_integration { viewport_id, parent_viewport_id, |ctx| { - render(ctx, viewport_id, parent_viewport_id); + render(ctx); }, ); let glutin = &mut *glutin.write(); @@ -1065,7 +1083,7 @@ mod glow_integration { return; } } - render(&egui_ctx, 0, 0); + render(&egui_ctx); }, ); @@ -1083,14 +1101,13 @@ mod glow_integration { fn process_viewport_builders( glutin_ctx: Arc>, mut viewports: Vec<( - u64, - u64, + ViewportId, + ViewportId, ViewportBuilder, - Option>>, + Option>>, )>, ) { - // 0 is the main viewport/window that will not be known by the egui_ctx - let mut active_viewports_ids = vec![0]; + let mut active_viewports_ids = vec![ViewportId::MAIN]; viewports.retain_mut(|(id, _, builder, render)| { if let Some(w) = glutin_ctx.read().windows.get(id) { @@ -1180,7 +1197,7 @@ mod glow_integration { }) } - fn get_window_winit_id(&self, id: u64) -> Option { + fn get_window_winit_id(&self, id: ViewportId) -> Option { self.running.read().as_ref().and_then(|r| { if let Some(window) = r.glutin_ctx.read().windows.get(&id) { return window.read().window.as_ref().map(|w| w.read().id()); @@ -1189,7 +1206,7 @@ mod glow_integration { }) } - fn get_window_id(&self, id: &winit::window::WindowId) -> Option { + fn get_window_id(&self, id: &winit::window::WindowId) -> Option { self.running .read() .as_ref() @@ -1203,7 +1220,7 @@ mod glow_integration { &running .glutin_ctx .read() - .window(0) + .window(ViewportId::MAIN) .read() .window .as_ref() @@ -1236,7 +1253,7 @@ mod glow_integration { // 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(); - if win.read().render.is_none() && viewport_id != 0 { + if win.read().render.is_none() && viewport_id != ViewportId::MAIN { if let Some(win) = glutin_ctx.read().windows.get(&win.read().parent_id) { win.read() .window @@ -1485,7 +1502,7 @@ mod glow_integration { .unwrap() .glutin_ctx .read() - .window(0) + .window(ViewportId::MAIN) .read() .window .as_ref() @@ -1584,7 +1601,13 @@ mod glow_integration { None } }) - .flat_map(|id| if id == 0 { Some(()) } else { None }) + .flat_map(|id| { + if id == ViewportId::MAIN { + Some(()) + } else { + None + } + }) .count() == 1 && running.integration.read().should_close() => @@ -1692,7 +1715,6 @@ mod wgpu_integration { use std::sync::Arc; use egui::ViewportRender; - use winit::window::ResizeDirection; use super::*; @@ -1701,12 +1723,12 @@ mod wgpu_integration { Arc< RwLock< HashMap< - u64, + ViewportId, ( Option>>, Arc>>, Option>>, - u64, + ViewportId, ViewportBuilder, ), >, @@ -1714,19 +1736,21 @@ mod wgpu_integration { >, ); + #[allow(unsafe_code)] unsafe impl Send for Windows {} + #[allow(unsafe_code)] unsafe impl Sync for Windows {} impl std::ops::Deref for Windows { type Target = Arc< RwLock< HashMap< - u64, + ViewportId, ( Option>>, Arc>>, Option>>, - u64, + ViewportId, ViewportBuilder, ), >, @@ -1746,7 +1770,7 @@ mod wgpu_integration { integration: Arc>, app: Box, windows: Windows, - windows_id: HashMap, + windows_id: HashMap, } struct WgpuWinitApp { @@ -1758,7 +1782,7 @@ mod wgpu_integration { /// Window surface state that's initialized when the app starts running via a Resumed event /// and on Android will also be destroyed if the application is paused. - is_focused: Arc>>, + is_focused: Arc>>, } impl WgpuWinitApp { @@ -1780,7 +1804,7 @@ mod wgpu_integration { native_options, running: None, app_creator: Some(app_creator), - is_focused: Arc::new(RwLock::new(Some(0))), + is_focused: Arc::new(RwLock::new(Some(ViewportId::MAIN))), } } @@ -1818,7 +1842,7 @@ mod wgpu_integration { } } - fn set_window(&mut self, id: u64) -> std::result::Result<(), egui_wgpu::WgpuError> { + fn set_window(&mut self, id: ViewportId) -> std::result::Result<(), egui_wgpu::WgpuError> { if let Some(running) = &mut self.running { if let Some((window, _, _, _, _)) = running.windows.read().get(&id) { window.as_ref().map(|w| { @@ -1856,7 +1880,7 @@ mod wgpu_integration { ), self.native_options.transparent, ); - pollster::block_on(painter.set_window(0, Some(&window)))?; + pollster::block_on(painter.set_window(ViewportId::MAIN, Some(&window)))?; let wgpu_render_state = painter.render_state(); @@ -1904,7 +1928,7 @@ mod wgpu_integration { .send_event(UserEvent::RequestRepaint { when, frame_nr, - window_id: info.window_id, + id: info.viewport_id, }) .ok(); }); @@ -1928,16 +1952,16 @@ mod wgpu_integration { } let mut windows_id = HashMap::default(); - windows_id.insert(window.id(), 0); + windows_id.insert(window.id(), ViewportId::MAIN); let windows = Windows(Arc::new(RwLock::new(HashMap::default()))); windows.write().insert( - 0, + ViewportId::MAIN, ( Some(Arc::new(RwLock::new(window))), Arc::new(RwLock::new(Some(state))), None, - 0, + ViewportId::MAIN, builder, ), ); @@ -1966,7 +1990,7 @@ mod wgpu_integration { viewport_id, parent_viewport_id, |ctx| { - render(ctx, viewport_id, parent_viewport_id); + render(ctx); }, ); @@ -1998,7 +2022,7 @@ mod wgpu_integration { } let mut viewports = output.viewports; - let mut active_viewports_ids = vec![0]; + let mut active_viewports_ids = vec![ViewportId::MAIN]; viewports.retain_mut(|(id, parent, builder, render)| { if let Some(w) = _windows.write().get_mut(id) { @@ -2027,7 +2051,7 @@ mod wgpu_integration { return; } } - render(&egui_ctx, 0, 0); + render(&egui_ctx); }, ); @@ -2078,7 +2102,7 @@ mod wgpu_integration { .flatten() } - fn get_window_winit_id(&self, id: u64) -> Option { + fn get_window_winit_id(&self, id: ViewportId) -> Option { self.running.as_ref().and_then(|r| { r.windows .read() @@ -2089,7 +2113,9 @@ mod wgpu_integration { fn save_and_destroy(&mut self) { if let Some(mut running) = self.running.take() { - if let Some((Some(window), _, _, _, _)) = running.windows.read().get(&0) { + if let Some((Some(window), _, _, _, _)) = + running.windows.read().get(&ViewportId::MAIN) + { running .integration .write() @@ -2130,7 +2156,8 @@ mod wgpu_integration { }; { let Some((viewport_id, (Some(window), state, render, parent_viewport_id, _))) = windows_id.get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]}; - if viewport_id != 0 && render.is_none() { + // 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) { window.0.as_ref().map(|w| w.read().request_redraw()); } @@ -2188,7 +2215,7 @@ mod wgpu_integration { integration.post_present(&window.read()); } - let mut active_viewports_ids = vec![0]; + let mut active_viewports_ids = vec![ViewportId::MAIN]; viewports.retain_mut(|(id, parent, builder, render)| { if let Some(w) = windows.write().get_mut(id) { @@ -2219,7 +2246,7 @@ mod wgpu_integration { .write() .retain(|id, _| active_viewports_ids.contains(id)); windows_id.retain(|_, id| active_viewports_ids.contains(id)); - painter.write().clean_surfaces(active_viewports_ids); + painter.write().clean_surfaces(&active_viewports_ids); let mut control_flow = vec![EventResult::Wait]; for repaint_after in repaint_after { @@ -2280,14 +2307,14 @@ mod wgpu_integration { Ok(match event { winit::event::Event::Resumed => { if let Some(running) = &self.running { - if running.windows.read().get(&0).is_none() { + if running.windows.read().get(&ViewportId::MAIN).is_none() { let window = Self::create_window( event_loop, running.integration.read().frame.storage(), &self.app_name, &self.native_options, )?; - self.set_window(0)?; + self.set_window(ViewportId::MAIN)?; } } else { let storage = epi_integration::create_storage( @@ -2310,7 +2337,7 @@ mod wgpu_integration { .unwrap() .windows .read() - .get(&0) + .get(&ViewportId::MAIN) .unwrap() .0 .as_ref() @@ -2458,7 +2485,7 @@ mod wgpu_integration { }) } - fn get_window_id(&self, id: &winit::window::WindowId) -> Option { + fn get_window_id(&self, id: &winit::window::WindowId) -> Option { self.running .as_ref() .and_then(|r| r.windows_id.get(id).cloned()) diff --git a/crates/egui-wgpu/Cargo.toml b/crates/egui-wgpu/Cargo.toml index 7fc095b2d..880b8f165 100644 --- a/crates/egui-wgpu/Cargo.toml +++ b/crates/egui-wgpu/Cargo.toml @@ -36,6 +36,7 @@ winit = ["dep:winit"] [dependencies] +egui = { version = "0.22.0", path = "../egui", default-features = false } epaint = { version = "0.22.0", path = "../epaint", default-features = false, features = [ "bytemuck", ] } diff --git a/crates/egui-wgpu/src/winit.rs b/crates/egui-wgpu/src/winit.rs index a96b64535..e23422551 100644 --- a/crates/egui-wgpu/src/winit.rs +++ b/crates/egui-wgpu/src/winit.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use egui::ViewportId; use epaint::ahash::HashMap; use crate::{renderer, RenderState, SurfaceErrorAction, WgpuConfiguration}; @@ -85,7 +86,7 @@ pub struct Painter { instance: wgpu::Instance, render_state: Option, - surfaces: HashMap, + surfaces: HashMap, } unsafe impl Send for Painter {} @@ -190,7 +191,7 @@ impl Painter { /// If the provided wgpu configuration does not match an available device. pub async fn set_window( &mut self, - viewport_id: u64, + viewport_id: ViewportId, window: Option<&winit::window::Window>, ) -> Result<(), crate::WgpuError> { match window { @@ -274,7 +275,7 @@ impl Painter { fn resize_and_generate_depth_texture_view_and_msaa_view( &mut self, - viewport_id: u64, + viewport_id: ViewportId, width_in_pixels: u32, height_in_pixels: u32, ) { @@ -334,7 +335,7 @@ impl Painter { pub fn on_window_resized( &mut self, - viewport_id: u64, + viewport_id: ViewportId, width_in_pixels: u32, height_in_pixels: u32, ) { @@ -451,7 +452,7 @@ impl Painter { // Returns a vector with the frame's pixel data if it was requested. pub fn paint_and_update_textures( &mut self, - viewport_id: u64, + viewport_id: ViewportId, pixels_per_point: f32, clear_color: [f32; 4], clipped_primitives: &[epaint::ClippedPrimitive], @@ -618,9 +619,9 @@ impl Painter { screenshot } - pub fn clean_surfaces(&mut self, avalibile_viewports: Vec) { + pub fn clean_surfaces(&mut self, avalibile_viewports: &[ViewportId]) { self.surfaces - .retain(|id, _| avalibile_viewports.contains(id)) + .retain(|id, _| avalibile_viewports.contains(id)); } #[allow(clippy::unused_self)] diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 496e214af..25cc32438 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -16,7 +16,7 @@ pub use accesskit_winit; pub use egui; #[cfg(feature = "accesskit")] use egui::accesskit; -use egui::{mutex::RwLock, ViewportCommand}; +use egui::{mutex::RwLock, ViewportCommand, ViewportId}; pub use winit; pub mod clipboard; @@ -905,9 +905,9 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option, - focused: Option, - get_window: impl Fn(u64) -> Option>>, + commands: Vec<(ViewportId, ViewportCommand)>, + focused: Option, + get_window: impl Fn(ViewportId) -> Option>>, ) { use winit::dpi::PhysicalSize; use winit::window::ResizeDirection; diff --git a/crates/egui/src/containers/window.rs b/crates/egui/src/containers/window.rs index 9100f2b98..34fbdb6d7 100644 --- a/crates/egui/src/containers/window.rs +++ b/crates/egui/src/containers/window.rs @@ -374,249 +374,242 @@ impl<'open> Window<'open> { window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32)); } - return ctx.create_viewport_sync( - window_builder, - move |ctx, viewport_id, parent_viewport_id| { - let mut op = is_open; - let open = if show_close_button { - Some(&mut op) - } else { - None - }; - let scroll = scroll.clone(); - let title = title.clone(); - let frame = frame - .unwrap_or_else(|| Frame::window(&ctx.style())) - .outer_margin(0.0) - .shadow(Shadow::NONE) - .stroke(Stroke::new( - 1.0, - if ctx.input(|i| i.focused) { - Color32::BLUE - } else { - Color32::BROWN - }, - )); - - area.show_open_close_animation(ctx, &frame, is_open); - - let area_id = area.id; - let area_layer_id = area.layer(); - let resize_id = area_id.with("resize"); - let mut collapsing = CollapsingState::load_with_default_open( - ctx, - area_id.with("collapsing"), - default_open, - ); - - let is_collapsed = with_title_bar && !collapsing.is_open(); - let possible = PossibleInteractions::new(&area, &resize, is_collapsed); - - let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it - let resize = resize.resizable(false); // We move it manually - let mut resize = resize.id(resize_id); - - let mut area = area.begin(ctx); - let win_size = ctx.input(|i| i.screen_rect.size()); - area.state_mut().set_left_top_pos(Pos2::ZERO); - area.state_mut().size = win_size; - let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y; - - let title_bar_height = if with_title_bar { - let style = ctx.style(); - ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing - } else { - 0.0 - }; - let margins = frame.outer_margin.sum() - + frame.inner_margin.sum() - + vec2(0.0, title_bar_height) - - vec2(0.0, 3.0); //magic number - - if let Some(mut state) = resize::State::load(ctx, resize_id) { - state.requested_size = Some(win_size - margins); - state.store(ctx, resize_id); - } - - // First interact (move etc) to avoid frame delay: - let last_frame_outer_rect = area.state().rect(); - - let interaction = if possible.movable || possible.resizable() { - window_interaction( - ctx, - possible, - area_layer_id, - area_id.with("frame_resize"), - last_frame_outer_rect, - ) - .and_then(|window_interaction| { - // Calculate roughly how much larger the window size is compared to the inner rect - - let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?; - let mut rect = window_interaction.start_rect; // prevent drift - - window_interaction.set_cursor(ctx); - if window_interaction.is_resize() { - ctx.viewport_command( - viewport_id, - ViewportCommand::Resize( - window_interaction.top, - window_interaction.bottom, - window_interaction.right, - window_interaction.left, - ), - ); - } else { - if ctx.input(|i| i.pointer.primary_pressed()) {} - } - ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id)); - - Some(window_interaction) - }) - } else { - None - }; - - let hover_interaction = - resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect); - - let mut area_content_ui = area.content_ui(ctx); - - let mut size = Vec2::new(1.0, 1.0); - - let content_inner = { - // BEGIN FRAME -------------------------------- - let frame_stroke = frame.stroke; - let mut frame = frame.begin(&mut area_content_ui); - - let title_bar = if with_title_bar { - let mut tmp_embedded = is_embedded; - - let title_bar = show_title_bar( - &mut frame.content_ui, - title, - show_close_button, - &mut collapsing, - collapsible, - area_id, - ); - - if tmp_embedded != is_embedded { - area_content_ui.data_mut(|data| { - data.insert_persisted( - area_id.with("_embedded"), - tmp_embedded, - ) - }); - } - resize.min_size.x = - resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width - Some(title_bar) + return ctx.create_viewport_sync(window_builder, move |ctx| { + let mut op = is_open; + let open = if show_close_button { + Some(&mut op) + } else { + None + }; + let scroll = scroll.clone(); + let title = title.clone(); + let frame = frame + .unwrap_or_else(|| Frame::window(&ctx.style())) + .outer_margin(0.0) + .shadow(Shadow::NONE) + .stroke(Stroke::new( + 1.0, + if ctx.input(|i| i.focused) { + Color32::BLUE } else { - None - }; + Color32::BROWN + }, + )); - let (content_inner, content_response) = collapsing - .show_body_unindented(&mut frame.content_ui, |ui| { - resize.show(ui, |ui| { - if title_bar.is_some() { - ui.add_space(title_content_spacing); - } + area.show_open_close_animation(ctx, &frame, is_open); - if scroll.has_any_bar() { - scroll.show(ui, |ui| add_contents(ui)).inner - } else { - add_contents(ui) - } - }) - }) - .map_or((None, None), |ir| (Some(ir.inner), Some(ir.response))); - if let Some(content_response) = &content_response { - size = content_response.rect.size() + let area_id = area.id; + let area_layer_id = area.layer(); + let resize_id = area_id.with("resize"); + let mut collapsing = CollapsingState::load_with_default_open( + ctx, + area_id.with("collapsing"), + default_open, + ); + + let is_collapsed = with_title_bar && !collapsing.is_open(); + let possible = PossibleInteractions::new(&area, &resize, is_collapsed); + + let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it + let resize = resize.resizable(false); // We move it manually + let mut resize = resize.id(resize_id); + + let mut area = area.begin(ctx); + let win_size = ctx.input(|i| i.screen_rect.size()); + area.state_mut().set_left_top_pos(Pos2::ZERO); + area.state_mut().size = win_size; + let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y; + + let title_bar_height = if with_title_bar { + let style = ctx.style(); + ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing + } else { + 0.0 + }; + let margins = frame.outer_margin.sum() + + frame.inner_margin.sum() + + vec2(0.0, title_bar_height) + - vec2(0.0, 3.0); //magic number + + if let Some(mut state) = resize::State::load(ctx, resize_id) { + state.requested_size = Some(win_size - margins); + state.store(ctx, resize_id); + } + + // First interact (move etc) to avoid frame delay: + let last_frame_outer_rect = area.state().rect(); + + let interaction = if possible.movable || possible.resizable() { + window_interaction( + ctx, + possible, + area_layer_id, + area_id.with("frame_resize"), + last_frame_outer_rect, + ) + .and_then(|window_interaction| { + // Calculate roughly how much larger the window size is compared to the inner rect + + let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?; + let mut rect = window_interaction.start_rect; // prevent drift + + window_interaction.set_cursor(ctx); + if window_interaction.is_resize() { + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::Resize( + window_interaction.top, + window_interaction.bottom, + window_interaction.right, + window_interaction.left, + ), + ); + } else { + if ctx.input(|i| i.pointer.primary_pressed()) {} } + ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id)); - let outer_rect = frame.end(&mut area_content_ui).rect; - paint_resize_corner( - &mut area_content_ui, - &possible, - outer_rect, - frame_stroke, + Some(window_interaction) + }) + } else { + None + }; + + let hover_interaction = + resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect); + + let mut area_content_ui = area.content_ui(ctx); + + let mut size = Vec2::new(1.0, 1.0); + + let content_inner = { + // BEGIN FRAME -------------------------------- + let frame_stroke = frame.stroke; + let mut frame = frame.begin(&mut area_content_ui); + + let title_bar = if with_title_bar { + let mut tmp_embedded = is_embedded; + + let title_bar = show_title_bar( + &mut frame.content_ui, + title, + show_close_button, + &mut collapsing, + collapsible, + area_id, ); - // END FRAME -------------------------------- - - if let Some(title_bar) = title_bar { - let res = title_bar.ui( - &mut area_content_ui, - outer_rect, - &content_response, - open, - &mut collapsing, - collapsible, - ); - if res.is_pointer_button_down_on() { - ctx.viewport_command(viewport_id, ViewportCommand::Drag); - } + if tmp_embedded != is_embedded { + area_content_ui.data_mut(|data| { + data.insert_persisted(area_id.with("_embedded"), tmp_embedded) + }); } + resize.min_size.x = resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width + Some(title_bar) + } else { + None + }; - collapsing.store(ctx); + let (content_inner, content_response) = collapsing + .show_body_unindented(&mut frame.content_ui, |ui| { + resize.show(ui, |ui| { + if title_bar.is_some() { + ui.add_space(title_content_spacing); + } - if let Some(interaction) = interaction { + if scroll.has_any_bar() { + scroll.show(ui, |ui| add_contents(ui)).inner + } else { + add_contents(ui) + } + }) + }) + .map_or((None, None), |ir| (Some(ir.inner), Some(ir.response))); + if let Some(content_response) = &content_response { + size = content_response.rect.size() + } + + let outer_rect = frame.end(&mut area_content_ui).rect; + paint_resize_corner( + &mut area_content_ui, + &possible, + outer_rect, + frame_stroke, + ); + + // END FRAME -------------------------------- + + if let Some(title_bar) = title_bar { + let res = title_bar.ui( + &mut area_content_ui, + outer_rect, + &content_response, + open, + &mut collapsing, + collapsible, + ); + if res.is_pointer_button_down_on() { + ctx.viewport_command(ctx.get_viewport_id(), ViewportCommand::Drag); + } + } + + collapsing.store(ctx); + + if let Some(interaction) = interaction { + paint_frame_interaction( + &mut area_content_ui, + outer_rect, + interaction, + ctx.style().visuals.widgets.active, + ); + } else if let Some(hover_interaction) = hover_interaction { + if ctx.input(|i| i.pointer.has_pointer()) { paint_frame_interaction( &mut area_content_ui, outer_rect, - interaction, - ctx.style().visuals.widgets.active, + hover_interaction, + ctx.style().visuals.widgets.hovered, ); - } else if let Some(hover_interaction) = hover_interaction { - if ctx.input(|i| i.pointer.has_pointer()) { - paint_frame_interaction( - &mut area_content_ui, - outer_rect, - hover_interaction, - ctx.style().visuals.widgets.hovered, - ); - } } - content_inner - }; - - let full_response = area.end(ctx, area_content_ui); - - if !collapsing.is_open() { - let size = ctx.round_vec_to_pixels(full_response.rect.size()); - ctx.viewport_command( - viewport_id, - ViewportCommand::InnerSize(size.x as u32, size.y as u32), - ); } + content_inner + }; - // let size = ctx.round_vec_to_pixels(full_response.rect.size()); - if win_size.x < size.x { - println!("Set size!"); - ctx.viewport_command( - viewport_id, - ViewportCommand::InnerSize(size.x as u32, win_size.y as u32), - ); - } - if win_size.y < size.y { - println!("Set size!"); - ctx.viewport_command( - viewport_id, - ViewportCommand::InnerSize(win_size.x as u32, size.y as u32), - ); - } - if show_close_button && op != is_open { - ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op)); - ctx.request_repaint_viewport(parent_viewport_id); - } + let full_response = area.end(ctx, area_content_ui); - return Some(InnerResponse { - inner: content_inner, - response: full_response, - }); - }, - ); + if !collapsing.is_open() { + let size = ctx.round_vec_to_pixels(full_response.rect.size()); + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::InnerSize(size.x as u32, size.y as u32), + ); + } + + // let size = ctx.round_vec_to_pixels(full_response.rect.size()); + if win_size.x < size.x { + println!("Set size!"); + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::InnerSize(size.x as u32, win_size.y as u32), + ); + } + if win_size.y < size.y { + println!("Set size!"); + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::InnerSize(win_size.x as u32, size.y as u32), + ); + } + if show_close_button && op != is_open { + ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op)); + ctx.request_repaint_viewport(ctx.get_parent_viewport_id()); + } + + return Some(InnerResponse { + inner: content_inner, + response: full_response, + }); + }); return None; } } @@ -849,234 +842,230 @@ impl<'open> Window<'open> { window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32)); } - ctx.create_viewport( - window_builder, - move |ctx, viewport_id, parent_viewport_id| { - let mut op = is_open; - let open = if show_close_button { - Some(&mut op) - } else { - None - }; - let scroll = scroll.clone(); - let title = title.clone(); - let frame = frame - .unwrap_or_else(|| Frame::window(&ctx.style())) - .outer_margin(0.0) - .shadow(Shadow::NONE) - .stroke(Stroke::new( - 1.0, - if ctx.input(|i| i.focused) { - Color32::BLUE - } else { - Color32::BROWN - }, - )); - - area.show_open_close_animation(ctx, &frame, is_open); - - let area_id = area.id; - let area_layer_id = area.layer(); - let resize_id = area_id.with("resize"); - let mut collapsing = CollapsingState::load_with_default_open( - ctx, - area_id.with("collapsing"), - default_open, - ); - - let is_collapsed = with_title_bar && !collapsing.is_open(); - let possible = PossibleInteractions::new(&area, &resize, is_collapsed); - - let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it - let resize = resize.resizable(false); // We move it manually - let mut resize = resize.id(resize_id); - - let mut area = area.begin(ctx); - let win_size = ctx.input(|i| i.screen_rect.size()); - area.state_mut().set_left_top_pos(Pos2::ZERO); - area.state_mut().size = win_size; - let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y; - - let title_bar_height = if with_title_bar { - let style = ctx.style(); - ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing - } else { - 0.0 - }; - let margins = frame.outer_margin.sum() - + frame.inner_margin.sum() - + vec2(0.0, title_bar_height) - - vec2(0.0, 3.0); //magic number - - if let Some(mut state) = resize::State::load(ctx, resize_id) { - state.requested_size = Some(win_size - margins); - state.store(ctx, resize_id); - } - - // First interact (move etc) to avoid frame delay: - let last_frame_outer_rect = area.state().rect(); - - let interaction = if possible.movable || possible.resizable() { - window_interaction( - ctx, - possible, - area_layer_id, - area_id.with("frame_resize"), - last_frame_outer_rect, - ) - .and_then(|window_interaction| { - // Calculate roughly how much larger the window size is compared to the inner rect - - let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?; - let mut rect = window_interaction.start_rect; // prevent drift - - window_interaction.set_cursor(ctx); - if window_interaction.is_resize() { - ctx.viewport_command( - viewport_id, - ViewportCommand::Resize( - window_interaction.top, - window_interaction.bottom, - window_interaction.right, - window_interaction.left, - ), - ); - } else { - if ctx.input(|i| i.pointer.primary_pressed()) {} - } - ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id)); - - Some(window_interaction) - }) - } else { - None - }; - - let hover_interaction = - resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect); - - let mut area_content_ui = area.content_ui(ctx); - - let mut size = Vec2::new(1.0, 1.0); - - let content_inner = { - // BEGIN FRAME -------------------------------- - let frame_stroke = frame.stroke; - let mut frame = frame.begin(&mut area_content_ui); - - let title_bar = if with_title_bar { - let title_bar = show_title_bar( - &mut frame.content_ui, - title, - show_close_button, - &mut collapsing, - collapsible, - area_id, - ); - - resize.min_size.x = - resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width - Some(title_bar) + ctx.create_viewport(window_builder, move |ctx| { + let mut op = is_open; + let open = if show_close_button { + Some(&mut op) + } else { + None + }; + let scroll = scroll.clone(); + let title = title.clone(); + let frame = frame + .unwrap_or_else(|| Frame::window(&ctx.style())) + .outer_margin(0.0) + .shadow(Shadow::NONE) + .stroke(Stroke::new( + 1.0, + if ctx.input(|i| i.focused) { + Color32::BLUE } else { - None - }; + Color32::BROWN + }, + )); - let (content_inner, content_response) = collapsing - .show_body_unindented(&mut frame.content_ui, |ui| { - resize.show(ui, |ui| { - if title_bar.is_some() { - ui.add_space(title_content_spacing); - } + area.show_open_close_animation(ctx, &frame, is_open); - if scroll.has_any_bar() { - scroll.show(ui, |ui| add_contents(ui)).inner - } else { - add_contents(ui) - } - }) - }) - .map_or((None, None), |ir| (Some(ir.inner), Some(ir.response))); - if let Some(content_response) = &content_response { - size = content_response.rect.size() + let area_id = area.id; + let area_layer_id = area.layer(); + let resize_id = area_id.with("resize"); + let mut collapsing = CollapsingState::load_with_default_open( + ctx, + area_id.with("collapsing"), + default_open, + ); + + let is_collapsed = with_title_bar && !collapsing.is_open(); + let possible = PossibleInteractions::new(&area, &resize, is_collapsed); + + let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it + let resize = resize.resizable(false); // We move it manually + let mut resize = resize.id(resize_id); + + let mut area = area.begin(ctx); + let win_size = ctx.input(|i| i.screen_rect.size()); + area.state_mut().set_left_top_pos(Pos2::ZERO); + area.state_mut().size = win_size; + let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y; + + let title_bar_height = if with_title_bar { + let style = ctx.style(); + ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing + } else { + 0.0 + }; + let margins = frame.outer_margin.sum() + + frame.inner_margin.sum() + + vec2(0.0, title_bar_height) + - vec2(0.0, 3.0); //magic number + + if let Some(mut state) = resize::State::load(ctx, resize_id) { + state.requested_size = Some(win_size - margins); + state.store(ctx, resize_id); + } + + // First interact (move etc) to avoid frame delay: + let last_frame_outer_rect = area.state().rect(); + + let interaction = if possible.movable || possible.resizable() { + window_interaction( + ctx, + possible, + area_layer_id, + area_id.with("frame_resize"), + last_frame_outer_rect, + ) + .and_then(|window_interaction| { + // Calculate roughly how much larger the window size is compared to the inner rect + + let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?; + let mut rect = window_interaction.start_rect; // prevent drift + + window_interaction.set_cursor(ctx); + if window_interaction.is_resize() { + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::Resize( + window_interaction.top, + window_interaction.bottom, + window_interaction.right, + window_interaction.left, + ), + ); + } else { + if ctx.input(|i| i.pointer.primary_pressed()) {} } + ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id)); - let outer_rect = frame.end(&mut area_content_ui).rect; - paint_resize_corner( - &mut area_content_ui, - &possible, - outer_rect, - frame_stroke, + Some(window_interaction) + }) + } else { + None + }; + + let hover_interaction = + resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect); + + let mut area_content_ui = area.content_ui(ctx); + + let mut size = Vec2::new(1.0, 1.0); + + let content_inner = { + // BEGIN FRAME -------------------------------- + let frame_stroke = frame.stroke; + let mut frame = frame.begin(&mut area_content_ui); + + let title_bar = if with_title_bar { + let title_bar = show_title_bar( + &mut frame.content_ui, + title, + show_close_button, + &mut collapsing, + collapsible, + area_id, ); - // END FRAME -------------------------------- + resize.min_size.x = resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width + Some(title_bar) + } else { + None + }; - if let Some(title_bar) = title_bar { - let res = title_bar.ui( - &mut area_content_ui, - outer_rect, - &content_response, - open, - &mut collapsing, - collapsible, - ); - if res.is_pointer_button_down_on() { - ctx.viewport_command(viewport_id, ViewportCommand::Drag); - } + let (content_inner, content_response) = collapsing + .show_body_unindented(&mut frame.content_ui, |ui| { + resize.show(ui, |ui| { + if title_bar.is_some() { + ui.add_space(title_content_spacing); + } + + if scroll.has_any_bar() { + scroll.show(ui, |ui| add_contents(ui)).inner + } else { + add_contents(ui) + } + }) + }) + .map_or((None, None), |ir| (Some(ir.inner), Some(ir.response))); + if let Some(content_response) = &content_response { + size = content_response.rect.size() + } + + let outer_rect = frame.end(&mut area_content_ui).rect; + paint_resize_corner( + &mut area_content_ui, + &possible, + outer_rect, + frame_stroke, + ); + + // END FRAME -------------------------------- + + if let Some(title_bar) = title_bar { + let res = title_bar.ui( + &mut area_content_ui, + outer_rect, + &content_response, + open, + &mut collapsing, + collapsible, + ); + if res.is_pointer_button_down_on() { + ctx.viewport_command(ctx.get_viewport_id(), ViewportCommand::Drag); } + } - collapsing.store(ctx); + collapsing.store(ctx); - if let Some(interaction) = interaction { + if let Some(interaction) = interaction { + paint_frame_interaction( + &mut area_content_ui, + outer_rect, + interaction, + ctx.style().visuals.widgets.active, + ); + } else if let Some(hover_interaction) = hover_interaction { + if ctx.input(|i| i.pointer.has_pointer()) { paint_frame_interaction( &mut area_content_ui, outer_rect, - interaction, - ctx.style().visuals.widgets.active, + hover_interaction, + ctx.style().visuals.widgets.hovered, ); - } else if let Some(hover_interaction) = hover_interaction { - if ctx.input(|i| i.pointer.has_pointer()) { - paint_frame_interaction( - &mut area_content_ui, - outer_rect, - hover_interaction, - ctx.style().visuals.widgets.hovered, - ); - } } - content_inner - }; + } + content_inner + }; - let full_response = area.end(ctx, area_content_ui); + let full_response = area.end(ctx, area_content_ui); - if !collapsing.is_open() { - let size = ctx.round_vec_to_pixels(full_response.rect.size()); - ctx.viewport_command( - viewport_id, - ViewportCommand::InnerSize(size.x as u32, size.y as u32), - ); - } + if !collapsing.is_open() { + let size = ctx.round_vec_to_pixels(full_response.rect.size()); + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::InnerSize(size.x as u32, size.y as u32), + ); + } - // let size = ctx.round_vec_to_pixels(full_response.rect.size()); - if win_size.x < size.x { - println!("Set size!"); - ctx.viewport_command( - viewport_id, - ViewportCommand::InnerSize(size.x as u32, win_size.y as u32), - ); - } - if win_size.y < size.y { - println!("Set size!"); - ctx.viewport_command( - viewport_id, - ViewportCommand::InnerSize(win_size.x as u32, size.y as u32), - ); - } - if show_close_button && op != is_open { - ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op)); - ctx.request_repaint_viewport(parent_viewport_id); - } - }, - ); + // let size = ctx.round_vec_to_pixels(full_response.rect.size()); + if win_size.x < size.x { + println!("Set size!"); + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::InnerSize(size.x as u32, win_size.y as u32), + ); + } + if win_size.y < size.y { + println!("Set size!"); + ctx.viewport_command( + ctx.get_viewport_id(), + ViewportCommand::InnerSize(win_size.x as u32, size.y as u32), + ); + } + if show_close_button && op != is_open { + ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op)); + ctx.request_repaint_viewport(ctx.get_parent_viewport_id()); + } + }); return; } } diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 312aa539c..0f9517353 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -23,8 +23,8 @@ pub struct RequestRepaintInfo { /// triggered the painting of the next frame. pub current_frame_nr: u64, - /// This is used to specify what window to redraw - pub window_id: u64, + /// This is used to specify what viewport that should be redraw + pub viewport_id: ViewportId, } // ---------------------------------------------------------------------------- @@ -60,10 +60,10 @@ struct Repaint { /// even if there's no new events. /// /// Also used to suppress multiple calls to the repaint callback during the same frame. - pub repaint_after: HashMap, + pub repaint_after: HashMap, /// While positive, keep requesting repaints. Decrement at the end of each frame. - repaint_requests: HashMap, + repaint_requests: HashMap, request_repaint_callback: Option>, requested_repaint_last_frame: bool, @@ -72,9 +72,9 @@ struct Repaint { impl Default for Repaint { fn default() -> Self { let mut repaint_after = HashMap::default(); - repaint_after.insert(0, std::time::Duration::from_millis(100)); + repaint_after.insert(ViewportId::MAIN, std::time::Duration::from_millis(100)); let mut repaint_requests = HashMap::default(); - repaint_requests.insert(0, 1); + repaint_requests.insert(ViewportId::MAIN, 1); Self { frame_nr: 0, repaint_after, @@ -88,11 +88,11 @@ impl Default for Repaint { } impl Repaint { - fn request_repaint(&mut self, window_id: u64) { - self.request_repaint_after(std::time::Duration::ZERO, window_id); + fn request_repaint(&mut self, viewport_id: ViewportId) { + self.request_repaint_after(std::time::Duration::ZERO, viewport_id); } - fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: u64) { + fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: ViewportId) { if after == std::time::Duration::ZERO { // Do a few extra frames to let things settle. // This is a bit of a hack, and we don't support it for `repaint_after` callbacks yet. @@ -114,14 +114,14 @@ impl Repaint { let info = RequestRepaintInfo { after, current_frame_nr: self.frame_nr, - window_id: viewport_id, + viewport_id, }; (callback)(info); } } } - fn start_frame(&mut self, viewport_id: u64) { + fn start_frame(&mut self, viewport_id: ViewportId) { // We are repainting; no need to reschedule a repaint unless the user asks for it again. self.repaint_after.remove(&viewport_id); } @@ -129,9 +129,9 @@ impl Repaint { // returns how long to wait until repaint fn end_frame( &mut self, - viewport_id: u64, - viewports: Vec, - ) -> Vec<(u64, std::time::Duration)> { + viewport_id: ViewportId, + viewports: Vec, + ) -> Vec<(ViewportId, std::time::Duration)> { // if repaint_requests is greater than zero. just set the duration to zero for immediate // repaint. if there's no repaint requests, then we can use the actual repaint_after instead. let repaint_after = if self @@ -180,17 +180,17 @@ struct ContextImpl { os: OperatingSystem, - input: HashMap, + input: HashMap, /// State that is collected during a frame and then cleared - frame_state: HashMap, + frame_state: HashMap, - // Viewport Id, Parent Viewport Id - frame_stack: Vec<(u64, u64)>, + /// Viewport Id, Parent Viewport Id + frame_stack: Vec<(ViewportId, ViewportId)>, // The output of a frame: - graphics: HashMap, - output: HashMap, + graphics: HashMap, + output: HashMap, paint_stats: PaintStats, @@ -200,19 +200,23 @@ struct ContextImpl { String, ( ViewportBuilder, - u64, - u64, + ViewportId, + ViewportId, bool, Option>>, ), >, - viewport_commands: Vec<(u64, ViewportCommand)>, + viewport_commands: Vec<(ViewportId, ViewportCommand)>, render_sync: Option< Arc< Box< - dyn for<'a> Fn(ViewportBuilder, u64, u64, Box) - + Send + dyn for<'a> Fn( + ViewportBuilder, + ViewportId, + ViewportId, + Box, + ) + Send + Sync, >, >, @@ -223,11 +227,11 @@ struct ContextImpl { /// Written to during the frame. layer_rects_this_frame: ahash::HashMap>, - layer_rects_this_viewports: HashMap>>, + layer_rects_this_viewports: HashMap>>, /// Read layer_rects_prev_frame: ahash::HashMap>, - layer_rects_prev_viewports: HashMap>>, + layer_rects_prev_viewports: HashMap>>, #[cfg(feature = "accesskit")] is_accesskit_enabled: bool, @@ -239,8 +243,8 @@ impl ContextImpl { fn begin_frame_mut( &mut self, mut new_raw_input: RawInput, - viewport_id: u64, - parent_viewport_id: u64, + viewport_id: ViewportId, + parent_viewport_id: ViewportId, ) { // This is used to pause the last frame if !self.frame_stack.is_empty() { @@ -377,11 +381,17 @@ impl ContextImpl { } impl ContextImpl { - pub(crate) fn get_viewport_id(&self) -> u64 { + // Return the `ViewportId` of the current viewport + // + // In the case of this viewport is the main viewport will be `ViewportId::MAIN` + pub(crate) fn get_viewport_id(&self) -> ViewportId { self.frame_stack.last().cloned().unwrap_or_default().0 } - pub(crate) fn get_parent_viewport_id(&self) -> u64 { + // Return the `ViewportId` of his parent + // + // In the case of this viewport is the main viewport will be `ViewportId::MAIN` + pub(crate) fn get_parent_viewport_id(&self) -> ViewportId { self.frame_stack.last().cloned().unwrap_or_default().1 } } @@ -460,7 +470,7 @@ impl Default for Context { s.write(|ctx| { ctx.render_sync = Some(Arc::new(Box::new( - move |_builder, _viewport_id, _parent_viewport_id, render| render(&clone, 0, 0), + move |_builder, _viewport_id, _parent_viewport_id, render| render(&clone), ))) }); @@ -505,8 +515,8 @@ impl Context { pub fn run( &self, new_input: RawInput, - viewport_id: u64, - parent_viewport_id: u64, + viewport_id: ViewportId, + parent_viewport_id: ViewportId, run_ui: impl FnOnce(&Context), ) -> FullOutput { self.begin_frame(new_input, viewport_id, parent_viewport_id); @@ -531,7 +541,12 @@ impl Context { /// let full_output = ctx.end_frame(); /// // handle full_output /// ``` - pub fn begin_frame(&self, new_input: RawInput, viewport_id: u64, parent_viewport_id: u64) { + pub fn begin_frame( + &self, + new_input: RawInput, + viewport_id: ViewportId, + parent_viewport_id: ViewportId, + ) { self.write(|ctx| ctx.begin_frame_mut(new_input, viewport_id, parent_viewport_id)); } } @@ -568,7 +583,7 @@ impl Context { /// Read-write access to [`InputState`]. #[inline] pub fn input_mut(&self, writer: impl FnOnce(&mut InputState) -> R) -> R { - self.write(move |ctx| writer(ctx.input.entry(ctx.viewport_counter).or_default())) + self.write(move |ctx| writer(ctx.input.entry(ctx.get_viewport_id()).or_default())) } /// Read-only access to [`Memory`]. @@ -1117,7 +1132,7 @@ impl Context { self.write(|ctx| ctx.repaint.request_repaint(ctx.get_viewport_id())); } - pub fn request_repaint_viewport(&self, id: u64) { + pub fn request_repaint_viewport(&self, id: ViewportId) { self.write(|ctx| ctx.repaint.request_repaint(id)) } @@ -1158,7 +1173,7 @@ impl Context { }); } - pub fn request_repaint_viewport_after(&self, duration: std::time::Duration, id: u64) { + pub fn request_repaint_viewport_after(&self, duration: std::time::Duration, id: ViewportId) { self.write(|ctx| ctx.repaint.request_repaint_after(duration, id)) } @@ -1376,7 +1391,7 @@ impl Context { /// Call at the end of each frame. #[must_use] pub fn end_frame(&self) -> FullOutput { - let mut viewports: Vec = self.write(|ctx| { + let mut viewports: Vec = self.write(|ctx| { ctx.layer_rects_prev_viewports.insert( ctx.get_viewport_id(), std::mem::take(&mut ctx.layer_rects_this_frame), @@ -1386,7 +1401,7 @@ impl Context { .map(|(_, (_, id, _, _, _))| *id) .collect() }); - viewports.push(0); + viewports.push(ViewportId::MAIN); if self.input(|i| i.wants_repaint()) { self.request_repaint(); @@ -1464,7 +1479,7 @@ impl Context { // This is used for, // If there are no viewport that contains the current viewpor that viewport needs to be destroyed! let avalibile_viewports = self.read(|ctx| { - let mut avalibile_viewports = vec![0]; + let mut avalibile_viewports = vec![ViewportId::MAIN]; for (_, (_, id, _, _, _)) in ctx.viewports.iter() { avalibile_viewports.push(*id); } @@ -2139,17 +2154,23 @@ impl Context { // Viewports impl Context { - pub fn get_viewport_id(&self) -> u64 { + // Return the `ViewportId` of the current viewport + // + // In the case of this viewport is the main viewport will be `ViewportId::MAIN` + pub fn get_viewport_id(&self) -> ViewportId { self.read(|ctx| ctx.get_viewport_id()) } - pub fn get_parent_viewport_id(&self) -> u64 { + // Return the `ViewportId` of his parent + // + // In the case of this viewport is the main viewport will be `ViewportId::MAIN` + pub fn get_parent_viewport_id(&self) -> ViewportId { self.read(|ctx| ctx.get_parent_viewport_id()) } pub fn set_render_sync_callback( &self, - callback: impl for<'a> Fn(ViewportBuilder, u64, u64, Box) + callback: impl for<'a> Fn(ViewportBuilder, ViewportId, ViewportId, Box) + Send + Sync + 'static, @@ -2166,14 +2187,14 @@ impl Context { self.write(|ctx| ctx.is_desktop = value) } - pub fn viewport_command(&self, id: u64, command: ViewportCommand) { + pub fn viewport_command(&self, id: ViewportId, command: ViewportCommand) { self.write(|ctx| ctx.viewport_commands.push((id, command))) } pub fn create_viewport( &self, viewport_builder: ViewportBuilder, - func: impl Fn(&Context, u64, u64) + Send + Sync + 'static, + func: impl Fn(&Context) + Send + Sync + 'static, ) { if self.is_desktop() { self.write(|ctx| { @@ -2184,8 +2205,8 @@ impl Context { window.3 = true; window.4 = Some(Arc::new(Box::new(func))); } else { - let id = ctx.viewport_counter + 1; - ctx.viewport_counter = id; + let id = ViewportId(ctx.viewport_counter + 1); + ctx.viewport_counter += 1; ctx.viewports.insert( viewport_builder.title.clone(), ( @@ -2199,18 +2220,18 @@ impl Context { } }); } else { - func(self, 0, 0); + func(self); } } pub fn create_viewport_sync( &self, viewport_builder: ViewportBuilder, - func: impl FnOnce(&Context, u64, u64) -> T, + func: impl FnOnce(&Context) -> T, ) -> T { if self.is_desktop() { - let mut viewport_id = 0; - let mut parent_viewport_id = 0; + let mut viewport_id = ViewportId::MAIN; + let mut parent_viewport_id = ViewportId::MAIN; let render_sync = self.write(|ctx| { viewport_id = ctx.get_viewport_id(); if let Some(window) = ctx.viewports.get_mut(&viewport_builder.title) { @@ -2221,8 +2242,8 @@ impl Context { viewport_id = window.1; parent_viewport_id = window.2; } else { - let id = ctx.viewport_counter + 1; - ctx.viewport_counter = id; + let id = ViewportId(ctx.viewport_counter + 1); + ctx.viewport_counter += 1; ctx.viewports.insert( viewport_builder.title.clone(), (viewport_builder.clone(), id, viewport_id, true, None), @@ -2240,15 +2261,13 @@ impl Context { viewport_builder, viewport_id, parent_viewport_id, - Box::new(move |context, viewport_id, parent_viewport_id| { - *out = Some(func(context, viewport_id, parent_viewport_id)) - }), + Box::new(move |context| *out = Some(func(context))), ); } out.unwrap() } else { - func(self, 0, 0) + func(self) } } } diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index ad9b7ba0a..8ea478836 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -2,8 +2,8 @@ use std::sync::Arc; -use crate::Context; use crate::{ViewportBuilder, ViewportCommand, WidgetType}; +use crate::{ViewportId, ViewportRender}; /// What egui emits each frame from [`crate::Context::run`]. /// @@ -21,7 +21,7 @@ pub struct FullOutput { /// duration elapses. when in reactive mode, egui spends forever waiting for input and only then, /// will it repaint itself. this can be used to make sure that backend will only wait for a /// specified amount of time, and repaint egui without any new input. - pub repaint_after: Vec<(u64, std::time::Duration)>, + pub repaint_after: Vec<(ViewportId, std::time::Duration)>, /// Texture changes since last frame (including the font texture). /// @@ -35,13 +35,13 @@ pub struct FullOutput { pub shapes: Vec, pub viewports: Vec<( - u64, - u64, + ViewportId, + ViewportId, ViewportBuilder, - Option>>, + Option>>, )>, - pub viewport_commands: Vec<(u64, ViewportCommand)>, + pub viewport_commands: Vec<(ViewportId, ViewportCommand)>, } impl FullOutput { diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index c44b00e44..2b4c69b94 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -554,20 +554,30 @@ pub enum WidgetType { pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) { let ctx = Context::default(); ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time) - let _ = ctx.run(Default::default(), 0, 0, |ctx| { - run_ui(ctx); - }); + let _ = ctx.run( + Default::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + run_ui(ctx); + }, + ); } /// For use in tests; especially doctests. pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) { let ctx = Context::default(); ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time) - let _ = ctx.run(Default::default(), 0, 0, |ctx| { - crate::CentralPanel::default().show(ctx, |ui| { - add_contents(ui); - }); - }); + let _ = ctx.run( + Default::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + crate::CentralPanel::default().show(ctx, |ui| { + add_contents(ui); + }); + }, + ); } #[cfg(feature = "accesskit")] diff --git a/crates/egui/src/memory.rs b/crates/egui/src/memory.rs index 3a94db53d..16c760b73 100644 --- a/crates/egui/src/memory.rs +++ b/crates/egui/src/memory.rs @@ -1,6 +1,6 @@ use ahash::HashMap; -use crate::{area, window, Id, IdMap, InputState, LayerId, Pos2, Rect, Style}; +use crate::{area, window, Id, IdMap, InputState, LayerId, Pos2, Rect, Style, ViewportId}; // ---------------------------------------------------------------------------- @@ -72,20 +72,20 @@ pub struct Memory { pub(crate) new_font_definitions: Option, #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) interactions: HashMap, + pub(crate) interactions: HashMap, #[cfg_attr(feature = "persistence", serde(skip))] pub(crate) interaction: Interaction, // Current viewport #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) viewport_id: u64, + pub(crate) viewport_id: ViewportId, #[cfg_attr(feature = "persistence", serde(skip))] pub(crate) window_interaction: Option, #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) window_interactions: HashMap, + pub(crate) window_interactions: HashMap, #[cfg_attr(feature = "persistence", serde(skip))] pub(crate) drag_value: crate::widgets::drag_value::MonoState, @@ -94,7 +94,7 @@ pub struct Memory { pub(crate) areas: Areas, #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) viewports_areas: HashMap, + pub(crate) viewports_areas: HashMap, /// Which popup-window is open (if any)? /// Could be a combo box, color picker, menu etc. @@ -370,7 +370,7 @@ impl Memory { &mut self, prev_input: &crate::input_state::InputState, new_input: &crate::data::input::RawInput, - viewport_id: u64, + viewport_id: ViewportId, ) { self.viewport_id = viewport_id; self.interactions @@ -389,7 +389,7 @@ impl Memory { } } - pub(crate) fn pause_frame(&mut self, viewport_id: u64) { + pub(crate) fn pause_frame(&mut self, viewport_id: ViewportId) { if let Some(window_interaction) = self.window_interaction { self.window_interactions .insert(viewport_id, window_interaction); @@ -403,7 +403,7 @@ impl Memory { pub(crate) fn end_frame( &mut self, input: &InputState, - viewports: &[u64], + viewports: &[ViewportId], used_ids: &IdMap, ) { self.caches.update(); @@ -420,7 +420,7 @@ impl Memory { .retain(|id, _| viewports.contains(id)); } - pub(crate) fn resume_frame(&mut self, viewport_id: u64) { + pub(crate) fn resume_frame(&mut self, viewport_id: ViewportId) { self.interaction = self.interactions.remove(&viewport_id).unwrap(); self.areas = self.viewports_areas.remove(&viewport_id).unwrap(); self.viewport_id = viewport_id; diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 3f2b604d6..bfc84b31b 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -1,11 +1,28 @@ -use std::sync::Arc; +use std::fmt::Display; use crate::Context; -/// This is used to render a viewport -pub type ViewportRender = dyn Fn(&Context, u64, u64) + Sync + Send; +/// This is used to send a command to a specific viewport +/// +/// This is returned by `Context::get_viewport_id` and `Context::get_parent_viewport_id` +#[derive(Default, Debug, Hash, Clone, Copy, PartialEq, Eq)] +pub struct ViewportId(pub(crate) u64); -#[derive(Hash, PartialEq, Clone)] +impl Display for ViewportId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl ViewportId { + /// This will return the `ViewportId` of the main viewport + pub const MAIN: Self = Self(0); +} + +/// This is used to render an async viewport +pub type ViewportRender = dyn Fn(&Context) + Sync + Send; + +#[derive(Hash, PartialEq, Eq, Clone)] pub struct ViewportBuilder { pub title: String, pub name: Option, diff --git a/crates/egui_demo_app/src/apps/custom3d_glow.rs b/crates/egui_demo_app/src/apps/custom3d_glow.rs index 4cef4a536..8ff3212ff 100644 --- a/crates/egui_demo_app/src/apps/custom3d_glow.rs +++ b/crates/egui_demo_app/src/apps/custom3d_glow.rs @@ -28,7 +28,7 @@ impl eframe::App for Custom3d { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/crates/egui_demo_app/src/wrap_app.rs b/crates/egui_demo_app/src/wrap_app.rs index 13513243a..6aea50014 100644 --- a/crates/egui_demo_app/src/wrap_app.rs +++ b/crates/egui_demo_app/src/wrap_app.rs @@ -21,7 +21,7 @@ impl eframe::App for EasyMarkApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } self.editor.panels(ctx); @@ -44,7 +44,7 @@ impl eframe::App for DemoApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } self.demo_windows.ui(ctx); @@ -67,7 +67,7 @@ impl eframe::App for FractalClockApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default() @@ -95,7 +95,7 @@ impl eframe::App for ColorTestApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { @@ -270,7 +270,7 @@ impl eframe::App for WrapApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } #[cfg(target_arch = "wasm32")] diff --git a/crates/egui_demo_lib/benches/benchmark.rs b/crates/egui_demo_lib/benches/benchmark.rs index eac580f1d..ddacda0ed 100644 --- a/crates/egui_demo_lib/benches/benchmark.rs +++ b/crates/egui_demo_lib/benches/benchmark.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use egui::epaint::TextShape; +use egui::{epaint::TextShape, ViewportId}; use egui_demo_lib::LOREM_IPSUM_LONG; pub fn criterion_benchmark(c: &mut Criterion) { @@ -13,24 +13,39 @@ pub fn criterion_benchmark(c: &mut Criterion) { // The most end-to-end benchmark. c.bench_function("demo_with_tessellate__realistic", |b| { b.iter(|| { - let full_output = ctx.run(RawInput::default(), 0, 0, |ctx| { - demo_windows.ui(ctx); - }); + let full_output = ctx.run( + RawInput::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + demo_windows.ui(ctx); + }, + ); ctx.tessellate(full_output.shapes) }); }); c.bench_function("demo_no_tessellate", |b| { b.iter(|| { - ctx.run(RawInput::default(), 0, 0, |ctx| { - demo_windows.ui(ctx); - }) + ctx.run( + RawInput::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + demo_windows.ui(ctx); + }, + ) }); }); - let full_output = ctx.run(RawInput::default(), 0, 0, |ctx| { - demo_windows.ui(ctx); - }); + let full_output = ctx.run( + RawInput::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + demo_windows.ui(ctx); + }, + ); c.bench_function("demo_only_tessellate", |b| { b.iter(|| ctx.tessellate(full_output.shapes.clone())); }); @@ -42,34 +57,44 @@ pub fn criterion_benchmark(c: &mut Criterion) { let mut demo_windows = egui_demo_lib::DemoWindows::default(); c.bench_function("demo_full_no_tessellate", |b| { b.iter(|| { - ctx.run(RawInput::default(), 0, 0, |ctx| { - demo_windows.ui(ctx); - }) + ctx.run( + RawInput::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + demo_windows.ui(ctx); + }, + ) }); }); } { let ctx = egui::Context::default(); - let _ = ctx.run(RawInput::default(), 0, 0, |ctx| { - egui::CentralPanel::default().show(ctx, |ui| { - c.bench_function("label &str", |b| { - b.iter(|| { - ui.label("the quick brown fox jumps over the lazy dog"); + let _ = ctx.run( + RawInput::default(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + egui::CentralPanel::default().show(ctx, |ui| { + c.bench_function("label &str", |b| { + b.iter(|| { + ui.label("the quick brown fox jumps over the lazy dog"); + }); + }); + c.bench_function("label format!", |b| { + b.iter(|| { + ui.label("the quick brown fox jumps over the lazy dog".to_owned()); + }); }); }); - c.bench_function("label format!", |b| { - b.iter(|| { - ui.label("the quick brown fox jumps over the lazy dog".to_owned()); - }); - }); - }); - }); + }, + ); } { let ctx = egui::Context::default(); - ctx.begin_frame(RawInput::default(), 0, 0); + ctx.begin_frame(RawInput::default(), ViewportId::MAIN, ViewportId::MAIN); egui::CentralPanel::default().show(&ctx, |ui| { c.bench_function("Painter::rect", |b| { diff --git a/crates/egui_demo_lib/src/lib.rs b/crates/egui_demo_lib/src/lib.rs index f9c3866bc..758b0adf2 100644 --- a/crates/egui_demo_lib/src/lib.rs +++ b/crates/egui_demo_lib/src/lib.rs @@ -19,6 +19,7 @@ pub mod syntax_highlighting; pub use color_test::ColorTest; pub use demo::DemoWindows; +use egui::ViewportId; // ---------------------------------------------------------------------------- @@ -68,9 +69,14 @@ fn test_egui_e2e() { const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { - let full_output = ctx.run(raw_input.clone(), 0, 0, |ctx| { - demo_windows.ui(ctx); - }); + let full_output = ctx.run( + raw_input.clone(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + demo_windows.ui(ctx); + }, + ); let clipped_primitives = ctx.tessellate(full_output.shapes); assert!(!clipped_primitives.is_empty()); } @@ -87,9 +93,14 @@ fn test_egui_zero_window_size() { const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { - let full_output = ctx.run(raw_input.clone(), 0, 0, |ctx| { - demo_windows.ui(ctx); - }); + let full_output = ctx.run( + raw_input.clone(), + ViewportId::MAIN, + ViewportId::MAIN, + |ctx| { + demo_windows.ui(ctx); + }, + ); let clipped_primitives = ctx.tessellate(full_output.shapes); assert!( clipped_primitives.is_empty(), diff --git a/examples/confirm_exit/src/main.rs b/examples/confirm_exit/src/main.rs index c26451148..24aee6932 100644 --- a/examples/confirm_exit/src/main.rs +++ b/examples/confirm_exit/src/main.rs @@ -34,7 +34,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/custom_3d_glow/src/main.rs b/examples/custom_3d_glow/src/main.rs index 34de52ef9..53e687831 100644 --- a/examples/custom_3d_glow/src/main.rs +++ b/examples/custom_3d_glow/src/main.rs @@ -48,7 +48,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/custom_font/src/main.rs b/examples/custom_font/src/main.rs index 5bd345fd0..5a57ba278 100644 --- a/examples/custom_font/src/main.rs +++ b/examples/custom_font/src/main.rs @@ -67,7 +67,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/custom_font_style/src/main.rs b/examples/custom_font_style/src/main.rs index 9e7f2f421..0904f24c0 100644 --- a/examples/custom_font_style/src/main.rs +++ b/examples/custom_font_style/src/main.rs @@ -71,7 +71,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, content); diff --git a/examples/custom_window_frame/src/main.rs b/examples/custom_window_frame/src/main.rs index ebd6d63fb..b120cbe14 100644 --- a/examples/custom_window_frame/src/main.rs +++ b/examples/custom_window_frame/src/main.rs @@ -37,7 +37,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } custom_window_frame(ctx, frame, "egui with custom frame", |ui| { diff --git a/examples/download_image/src/main.rs b/examples/download_image/src/main.rs index c2b940967..36e9bc4e9 100644 --- a/examples/download_image/src/main.rs +++ b/examples/download_image/src/main.rs @@ -28,7 +28,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } let promise = self.promise.get_or_insert_with(|| { diff --git a/examples/file_dialog/src/main.rs b/examples/file_dialog/src/main.rs index b1288ad76..ba82e3de0 100644 --- a/examples/file_dialog/src/main.rs +++ b/examples/file_dialog/src/main.rs @@ -30,7 +30,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/hello_world/src/main.rs b/examples/hello_world/src/main.rs index 70a8724dc..9393861b9 100644 --- a/examples/hello_world/src/main.rs +++ b/examples/hello_world/src/main.rs @@ -37,7 +37,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/hello_world_par/src/main.rs b/examples/hello_world_par/src/main.rs index 1dbb953a3..317306a41 100644 --- a/examples/hello_world_par/src/main.rs +++ b/examples/hello_world_par/src/main.rs @@ -123,7 +123,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::Window::new("Main thread").show(ctx, |ui| { diff --git a/examples/keyboard_events/src/main.rs b/examples/keyboard_events/src/main.rs index 983edf83f..a6f7d71b5 100644 --- a/examples/keyboard_events/src/main.rs +++ b/examples/keyboard_events/src/main.rs @@ -26,7 +26,7 @@ impl eframe::App for Content { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/puffin_profiler/src/main.rs b/examples/puffin_profiler/src/main.rs index fbaa4d33c..8473d062e 100644 --- a/examples/puffin_profiler/src/main.rs +++ b/examples/puffin_profiler/src/main.rs @@ -24,7 +24,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/retained_image/src/main.rs b/examples/retained_image/src/main.rs index 785e5aebe..171f16a5d 100644 --- a/examples/retained_image/src/main.rs +++ b/examples/retained_image/src/main.rs @@ -42,7 +42,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index 713124838..d63d94f96 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -31,7 +31,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/serial_windows/src/main.rs b/examples/serial_windows/src/main.rs index 01621414a..8d787adc4 100644 --- a/examples/serial_windows/src/main.rs +++ b/examples/serial_windows/src/main.rs @@ -53,7 +53,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index 7037a0796..4ee7f7145 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -44,7 +44,7 @@ impl eframe::App for MyApp { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } egui::CentralPanel::default().show(ctx, |ui| { diff --git a/examples/user_attention/src/main.rs b/examples/user_attention/src/main.rs index 7f92f9fae..4c516dd6d 100644 --- a/examples/user_attention/src/main.rs +++ b/examples/user_attention/src/main.rs @@ -61,7 +61,7 @@ impl eframe::App for Application { render: Option<&ViewportRender>, ) { if let Some(render) = render { - render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id()); + render(ctx); return; } if let Some(request_at) = self.request_at { diff --git a/examples/viewports/src/main.rs b/examples/viewports/src/main.rs index 1f723f143..a64368c6d 100644 --- a/examples/viewports/src/main.rs +++ b/examples/viewports/src/main.rs @@ -39,7 +39,9 @@ fn main() { if show_sync { ctx.create_viewport_sync( ViewportBuilder::default().with_title("Sync rendering!"), - |ctx, viewport_id, parent_viewport_id| { + |ctx| { + let viewport_id = ctx.get_viewport_id(); + let parent_viewport_id = ctx.get_parent_viewport_id(); egui::CentralPanel::default().show(ctx, |ui| { ui.label(format!("Frame: {}", ui.ctx().frame_nr())); ui.horizontal(|ui| {