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

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

This commit is contained in:
Konkitoman
2023-08-09 18:33:59 +03:00
parent 1a7c4700fd
commit 86ef11c521
34 changed files with 775 additions and 663 deletions

1
Cargo.lock generated
View File

@@ -1195,6 +1195,7 @@ version = "0.22.0"
dependencies = [
"bytemuck",
"document-features",
"egui",
"epaint",
"log",
"puffin",

View File

@@ -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<U> {
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)
}
}
}

View File

@@ -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<Arc<Box<dyn Fn(&Context, u64, u64) + Sync + Send>>>,
viewport_id: u64,
parent_id: u64,
render: Option<Arc<Box<ViewportRender>>>,
viewport_id: egui::ViewportId,
parent_id: egui::ViewportId,
) -> egui::FullOutput {
let frame_start = std::time::Instant::now();

View File

@@ -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<Arc<RwLock<winit::window::Window>>>;
fn get_window_winit_id(&self, id: u64) -> Option<winit::window::WindowId>;
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<u64>;
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId>;
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId>;
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<UserEvent>, 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<glutin::surface::Surface<glutin::surface::WindowSurface>>,
window: Option<Arc<RwLock<winit::window::Window>>>,
window_id: u64,
parent_id: u64,
window_id: ViewportId,
parent_id: ViewportId,
render: Option<Arc<Box<ViewportRender>>>,
pub egui_winit: Option<egui_winit::State>,
}
@@ -487,11 +487,13 @@ mod glow_integration {
current_gl_context: Option<glutin::context::PossiblyCurrentContext>,
not_current_gl_context: Option<glutin::context::NotCurrentContext>,
windows: HashMap<u64, Arc<RwLock<Window>>>,
window_maps: HashMap<winit::window::WindowId, u64>,
windows: HashMap<ViewportId, Arc<RwLock<Window>>>,
window_maps: HashMap<winit::window::WindowId, ViewportId>,
}
#[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<RwLock<Window>> {
fn window(&self, viewport_id: ViewportId) -> Arc<RwLock<Window>> {
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<u32>) {
fn resize(
&mut self,
viewport_id: ViewportId,
physical_size: winit::dpi::PhysicalSize<u32>,
) {
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<epi::AppCreator>,
is_focused: Arc<RwLock<Option<u64>>>,
is_focused: Arc<RwLock<Option<ViewportId>>>,
}
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<RwLock<GlutinWindowContext>>,
mut viewports: Vec<(
u64,
u64,
ViewportId,
ViewportId,
ViewportBuilder,
Option<Arc<Box<dyn Fn(&egui::Context, u64, u64) + Sync + Send>>>,
Option<Arc<Box<ViewportRender>>>,
)>,
) {
// 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<winit::window::WindowId> {
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId> {
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<u64> {
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId> {
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<RwLock<winit::window::Window>>>,
Arc<RwLock<Option<egui_winit::State>>>,
Option<Arc<Box<ViewportRender>>>,
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<RwLock<winit::window::Window>>>,
Arc<RwLock<Option<egui_winit::State>>>,
Option<Arc<Box<ViewportRender>>>,
u64,
ViewportId,
ViewportBuilder,
),
>,
@@ -1746,7 +1770,7 @@ mod wgpu_integration {
integration: Arc<RwLock<epi_integration::EpiIntegration>>,
app: Box<dyn epi::App>,
windows: Windows,
windows_id: HashMap<winit::window::WindowId, u64>,
windows_id: HashMap<winit::window::WindowId, ViewportId>,
}
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<RwLock<Option<u64>>>,
is_focused: Arc<RwLock<Option<ViewportId>>>,
}
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<winit::window::WindowId> {
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId> {
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<u64> {
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId> {
self.running
.as_ref()
.and_then(|r| r.windows_id.get(id).cloned())

View File

@@ -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",
] }

View File

@@ -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<RenderState>,
surfaces: HashMap<u64, SurfaceState>,
surfaces: HashMap<ViewportId, SurfaceState>,
}
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<u64>) {
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)]

View File

@@ -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<winit::window::Curs
}
pub fn process_viewport_commands(
commands: Vec<(u64, ViewportCommand)>,
focused: Option<u64>,
get_window: impl Fn(u64) -> Option<Arc<RwLock<winit::window::Window>>>,
commands: Vec<(ViewportId, ViewportCommand)>,
focused: Option<ViewportId>,
get_window: impl Fn(ViewportId) -> Option<Arc<RwLock<winit::window::Window>>>,
) {
use winit::dpi::PhysicalSize;
use winit::window::ResizeDirection;

View File

@@ -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;
}
}

View File

@@ -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<u64, std::time::Duration>,
pub repaint_after: HashMap<ViewportId, std::time::Duration>,
/// While positive, keep requesting repaints. Decrement at the end of each frame.
repaint_requests: HashMap<u64, u32>,
repaint_requests: HashMap<ViewportId, u32>,
request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
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<u64>,
) -> Vec<(u64, std::time::Duration)> {
viewport_id: ViewportId,
viewports: Vec<ViewportId>,
) -> 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<u64, InputState>,
input: HashMap<ViewportId, InputState>,
/// State that is collected during a frame and then cleared
frame_state: HashMap<u64, FrameState>,
frame_state: HashMap<ViewportId, FrameState>,
// 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<u64, GraphicLayers>,
output: HashMap<u64, PlatformOutput>,
graphics: HashMap<ViewportId, GraphicLayers>,
output: HashMap<ViewportId, PlatformOutput>,
paint_stats: PaintStats,
@@ -200,19 +200,23 @@ struct ContextImpl {
String,
(
ViewportBuilder,
u64,
u64,
ViewportId,
ViewportId,
bool,
Option<Arc<Box<ViewportRender>>>,
),
>,
viewport_commands: Vec<(u64, ViewportCommand)>,
viewport_commands: Vec<(ViewportId, ViewportCommand)>,
render_sync: Option<
Arc<
Box<
dyn for<'a> Fn(ViewportBuilder, u64, u64, Box<dyn FnOnce(&Context, u64, u64) + 'a>)
+ Send
dyn for<'a> Fn(
ViewportBuilder,
ViewportId,
ViewportId,
Box<dyn FnOnce(&Context) + 'a>,
) + Send
+ Sync,
>,
>,
@@ -223,11 +227,11 @@ struct ContextImpl {
/// Written to during the frame.
layer_rects_this_frame: ahash::HashMap<LayerId, Vec<(Id, Rect)>>,
layer_rects_this_viewports: HashMap<u64, HashMap<LayerId, Vec<(Id, Rect)>>>,
layer_rects_this_viewports: HashMap<ViewportId, HashMap<LayerId, Vec<(Id, Rect)>>>,
/// Read
layer_rects_prev_frame: ahash::HashMap<LayerId, Vec<(Id, Rect)>>,
layer_rects_prev_viewports: HashMap<u64, HashMap<LayerId, Vec<(Id, Rect)>>>,
layer_rects_prev_viewports: HashMap<ViewportId, HashMap<LayerId, Vec<(Id, Rect)>>>,
#[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<R>(&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<u64> = self.write(|ctx| {
let mut viewports: Vec<ViewportId> = 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<dyn FnOnce(&Context, u64, u64) + 'a>)
callback: impl for<'a> Fn(ViewportBuilder, ViewportId, ViewportId, Box<dyn FnOnce(&Context) + 'a>)
+ 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<T>(
&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)
}
}
}

View File

@@ -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<epaint::ClippedShape>,
pub viewports: Vec<(
u64,
u64,
ViewportId,
ViewportId,
ViewportBuilder,
Option<Arc<Box<dyn Fn(&Context, u64, u64) + Sync + Send>>>,
Option<Arc<Box<ViewportRender>>>,
)>,
pub viewport_commands: Vec<(u64, ViewportCommand)>,
pub viewport_commands: Vec<(ViewportId, ViewportCommand)>,
}
impl FullOutput {

View File

@@ -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")]

View File

@@ -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<epaint::text::FontDefinitions>,
#[cfg_attr(feature = "persistence", serde(skip))]
pub(crate) interactions: HashMap<u64, Interaction>,
pub(crate) interactions: HashMap<ViewportId, Interaction>,
#[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<window::WindowInteraction>,
#[cfg_attr(feature = "persistence", serde(skip))]
pub(crate) window_interactions: HashMap<u64, window::WindowInteraction>,
pub(crate) window_interactions: HashMap<ViewportId, window::WindowInteraction>,
#[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<u64, Areas>,
pub(crate) viewports_areas: HashMap<ViewportId, Areas>,
/// 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<Rect>,
) {
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;

View File

@@ -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<String>,

View File

@@ -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| {

View File

@@ -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")]

View File

@@ -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| {

View File

@@ -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(),

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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);

View File

@@ -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| {

View File

@@ -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(|| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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| {

View File

@@ -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 {

View File

@@ -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| {