From 9c6044aa7dbbd420c640650eb641e9bbb011cfd1 Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Thu, 10 Aug 2023 16:53:31 +0300 Subject: [PATCH] Change ViewportBuilder how it's working --- crates/eframe/src/native/epi_integration.rs | 22 ++-- crates/eframe/src/native/run.rs | 46 +++---- crates/egui-winit/src/window_settings.rs | 7 +- crates/egui/src/containers/window.rs | 34 +++--- crates/egui/src/viewport.rs | 129 ++++++++++++-------- 5 files changed, 143 insertions(+), 95 deletions(-) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 055cd1566..599c183f7 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -106,7 +106,11 @@ pub fn window_builder( .with_maximized(*maximized) .with_resizable(*resizable) .with_transparent(*transparent) - .with_window_icon(icon_data.clone().map(|d| (d.width, d.height, d.rgba))) + .with_window_icon( + icon_data + .clone() + .map(|d| Arc::new((d.width, d.height, d.rgba))), + ) .with_active(*active) // Keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279 // We must also keep the window hidden until AccessKit is initialized. @@ -127,10 +131,12 @@ pub fn window_builder( } if let Some(min_size) = *min_window_size { - window_builder = window_builder.with_min_inner_size((min_size.x as u32, min_size.y as u32)); + window_builder = + window_builder.with_min_inner_size(Some((min_size.x as u32, min_size.y as u32))); } if let Some(max_size) = *max_window_size { - window_builder = window_builder.with_max_inner_size((max_size.x as u32, max_size.y as u32)); + window_builder = + window_builder.with_max_inner_size(Some((max_size.x as u32, max_size.y as u32))); } window_builder = window_builder.with_drag_and_drop(*drag_and_drop_support); @@ -144,14 +150,16 @@ pub fn window_builder( window_settings.inner_size_points() } else { if let Some(pos) = *initial_window_pos { - window_builder = window_builder.with_position((pos.x as i32, pos.y as i32)); + window_builder = window_builder.with_position(Some((pos.x as i32, pos.y as i32))); } if let Some(initial_window_size) = *initial_window_size { let initial_window_size = initial_window_size.at_most(largest_monitor_point_size(event_loop)); - window_builder = window_builder - .with_inner_size((initial_window_size.x as u32, initial_window_size.y as u32)); + window_builder = window_builder.with_inner_size(Some(( + initial_window_size.x as u32, + initial_window_size.y as u32, + ))); } *initial_window_size @@ -164,7 +172,7 @@ pub fn window_builder( if monitor_size.width > 0.0 && monitor_size.height > 0.0 { let x = (monitor_size.width - inner_size.x as f64) / 2.0; let y = (monitor_size.height - inner_size.y as f64) / 2.0; - window_builder = window_builder.with_position((x as i32, y as i32)); + window_builder = window_builder.with_position(Some((x as i32, y as i32))); } } } diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 00f07a7c9..bbf9fc9c0 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, ViewportId}; +use egui::{epaint::ahash::HashMap, mutex::RwLock, ViewportBuilder, ViewportCommand, ViewportId}; use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; use winit::{ event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget}, @@ -1104,11 +1104,6 @@ mod glow_integration { if let Some(w) = glutin_ctx.read().windows.get(id) { let mut w = w.write(); if w.builder != *builder { - if let Some(window) = &mut w.window { - if let Ok(pos) = window.read().outer_position() { - builder.position = Some((pos.x, pos.y)); - } - } w.window = None; w.gl_surface = None; w.render = render.clone(); @@ -2526,49 +2521,50 @@ fn extremely_far_future() -> std::time::Instant { fn create_winit_window_builder(builder: &ViewportBuilder) -> winit::window::WindowBuilder { let mut window_builder = winit::window::WindowBuilder::new() .with_title(builder.title.clone()) - .with_transparent(builder.transparent) - .with_decorations(builder.decorations) - .with_resizable(builder.resizable) - .with_visible(builder.visible) + .with_transparent(builder.transparent.map_or(false, |e| e)) + .with_decorations(builder.decorations.map_or(false, |e| e)) + .with_resizable(builder.resizable.map_or(false, |e| e)) + .with_visible(builder.visible.map_or(false, |e| e)) .with_fullscreen( builder .fullscreen - .then_some(winit::window::Fullscreen::Borderless(None)), + .map(|e| e.then(|| winit::window::Fullscreen::Borderless(None))) + .flatten(), ) .with_enabled_buttons( WindowButtons::MAXIMIZE | WindowButtons::MINIMIZE - | if builder.close_button { - WindowButtons::CLOSE - } else { - WindowButtons::empty() - }, + | builder + .close_button + .map(|v| v.then(|| WindowButtons::CLOSE)) + .flatten() + .unwrap_or(WindowButtons::empty()), ) - .with_active(builder.active); - if let Some(inner_size) = builder.inner_size { + .with_active(builder.active.map_or(false, |e| e)); + if let Some(Some(inner_size)) = builder.inner_size { window_builder = window_builder .with_inner_size(winit::dpi::PhysicalSize::new(inner_size.0, inner_size.1)); } - if let Some(min_inner_size) = builder.min_inner_size { + if let Some(Some(min_inner_size)) = builder.min_inner_size { window_builder = window_builder.with_min_inner_size(winit::dpi::PhysicalSize::new( min_inner_size.0, min_inner_size.1, )); } - if let Some(max_inner_size) = builder.max_inner_size { + if let Some(Some(max_inner_size)) = builder.max_inner_size { window_builder = window_builder.with_max_inner_size(winit::dpi::PhysicalSize::new( max_inner_size.0, max_inner_size.1, )); } - if let Some(position) = builder.position { + if let Some(Some(position)) = builder.position { window_builder = window_builder.with_position(winit::dpi::PhysicalPosition::new(position.0, position.1)); } - if let Some(icon) = builder.icon.clone() { + if let Some(Some(icon)) = builder.icon.clone() { window_builder = window_builder.with_window_icon(load_icon(crate::IconData { - rgba: icon.2, + rgba: icon.2.clone(), width: icon.0, height: icon.1, })); @@ -2576,3 +2572,7 @@ fn create_winit_window_builder(builder: &ViewportBuilder) -> winit::window::Wind window_builder } + +fn changes_betwen_builders(now: &ViewportBuilder, last: &ViewportBuilder) -> Vec { + vec![] +} diff --git a/crates/egui-winit/src/window_settings.rs b/crates/egui-winit/src/window_settings.rs index eb26f0e9c..a2642410c 100644 --- a/crates/egui-winit/src/window_settings.rs +++ b/crates/egui-winit/src/window_settings.rs @@ -55,12 +55,15 @@ impl WindowSettings { // If this happens on Windows, the clamping behavior is managed by the function // clamp_window_to_sane_position. if let Some(pos) = self.position { - window = window.with_position((pos.x as i32, pos.y as i32)); + window = window.with_position(Some((pos.x as i32, pos.y as i32))); } if let Some(inner_size_points) = self.inner_size_points { window - .with_inner_size((inner_size_points.x as u32, inner_size_points.y as u32)) + .with_inner_size(Some(( + inner_size_points.x as u32, + inner_size_points.y as u32, + ))) .with_fullscreen(self.fullscreen) } else { window diff --git a/crates/egui/src/containers/window.rs b/crates/egui/src/containers/window.rs index d4c930381..19f696f25 100644 --- a/crates/egui/src/containers/window.rs +++ b/crates/egui/src/containers/window.rs @@ -355,15 +355,16 @@ impl<'open> Window<'open> { if let Some(size) = ctx.data(|data| data.get_temp::(area.id.with("size"))) { let size = size.round() + ctx.style().spacing.window_margin.sum() * ctx.pixels_per_point(); - window_builder = - window_builder.with_inner_size((size.x as u32 + 1, size.y as u32 + 1)); + window_builder = window_builder + .with_inner_size(Some((size.x as u32 + 1, size.y as u32 + 1))); } else { ctx.request_repaint(); break 'create_viewport; } - window_builder.close_button = open.is_some(); - window_builder.resizable = resize.is_resizable(); - window_builder.decorations = !with_title_bar; + window_builder = window_builder + .with_close_button(open.is_some()) + .with_resizable(resize.is_resizable()) + .with_decorations(!with_title_bar); let pix = ctx.pixels_per_point(); let min_size = resize.min_size * pix; let max_size = resize.max_size * pix; @@ -372,9 +373,11 @@ impl<'open> Window<'open> { } else { Some(max_size) }; - window_builder.min_inner_size = Some((min_size.x as u32, min_size.y as u32)); + window_builder = window_builder + .with_min_inner_size(Some((min_size.x as u32, min_size.y as u32))); if let Some(max_size) = max_size { - window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32)); + window_builder = window_builder + .with_max_inner_size(Some((max_size.x as u32, max_size.y as u32))); } return ctx.create_viewport_sync(window_builder, move |ctx| { @@ -809,15 +812,16 @@ impl<'open> Window<'open> { if let Some(size) = ctx.data(|data| data.get_temp::(area.id.with("size"))) { let size = size.round() + ctx.style().spacing.window_margin.sum() * ctx.pixels_per_point(); - window_builder = - window_builder.with_inner_size((size.x as u32 + 1, size.y as u32 + 1)); + window_builder = window_builder + .with_inner_size(Some((size.x as u32 + 1, size.y as u32 + 1))); } else { ctx.request_repaint(); break 'create_viewport; } - window_builder.close_button = open.is_some(); - window_builder.resizable = resize.is_resizable(); - window_builder.decorations = !with_title_bar; + window_builder = window_builder + .with_close_button(open.is_some()) + .with_resizable(resize.is_resizable()) + .with_decorations(!with_title_bar); let pix = ctx.pixels_per_point(); let min_size = resize.min_size * pix; let max_size = resize.max_size * pix; @@ -826,9 +830,11 @@ impl<'open> Window<'open> { } else { Some(max_size) }; - window_builder.min_inner_size = Some((min_size.x as u32, min_size.y as u32)); + window_builder = window_builder + .with_min_inner_size(Some((min_size.x as u32, min_size.y as u32))); if let Some(max_size) = max_size { - window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32)); + window_builder = window_builder + .with_max_inner_size(Some((max_size.x as u32, max_size.y as u32))); } ctx.create_viewport(window_builder, move |ctx| { diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 866d5bd2a..18c5a4eec 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use std::{fmt::Display, sync::Arc}; use crate::Context; @@ -22,28 +22,30 @@ impl ViewportId { /// This is used to render an async viewport pub type ViewportRender = dyn Fn(&Context) + Sync + Send; +/// The filds in this struct should not be change directly, but is not problem tho! +/// Every thing is wraped in Option<> indicates that thing should not be changed! #[derive(Hash, PartialEq, Eq, Clone)] pub struct ViewportBuilder { pub title: String, pub name: Option, - pub position: Option<(i32, i32)>, - pub inner_size: Option<(u32, u32)>, - pub fullscreen: bool, - pub maximized: bool, - pub resizable: bool, - pub transparent: bool, - pub decorations: bool, - pub icon: Option<(u32, u32, Vec)>, - pub active: bool, - pub visible: bool, - pub title_hidden: bool, - pub titlebar_transparent: bool, - pub fullsize_content_view: bool, - pub min_inner_size: Option<(u32, u32)>, - pub max_inner_size: Option<(u32, u32)>, - pub drag_and_drop: bool, + pub position: Option>, + pub inner_size: Option>, + pub fullscreen: Option, + pub maximized: Option, + pub resizable: Option, + pub transparent: Option, + pub decorations: Option, + pub icon: Option)>>>, + pub active: Option, + pub visible: Option, + pub title_hidden: Option, + pub titlebar_transparent: Option, + pub fullsize_content_view: Option, + pub min_inner_size: Option>, + pub max_inner_size: Option>, + pub drag_and_drop: Option, - pub close_button: bool, + pub close_button: Option, } impl Default for ViewportBuilder { @@ -52,108 +54,137 @@ impl Default for ViewportBuilder { title: "Dummy EGUI Window".into(), name: None, position: None, - inner_size: Some((300, 100)), - fullscreen: false, - maximized: false, - resizable: true, - transparent: false, - decorations: true, + inner_size: Some(Some((300, 200))), + fullscreen: None, + maximized: None, + resizable: Some(true), + transparent: Some(true), + decorations: Some(true), icon: None, - active: true, - visible: true, - title_hidden: false, - titlebar_transparent: false, - fullsize_content_view: false, + active: Some(true), + visible: Some(true), + title_hidden: None, + titlebar_transparent: None, + fullsize_content_view: None, min_inner_size: None, max_inner_size: None, - drag_and_drop: true, - close_button: true, + drag_and_drop: None, + close_button: None, } } } impl ViewportBuilder { + pub fn empty() -> Self { + Self { + title: "Dummy EGUI Window".into(), + name: None, + position: None, + inner_size: None, + fullscreen: None, + maximized: None, + resizable: None, + transparent: None, + decorations: None, + icon: None, + active: None, + visible: None, + title_hidden: None, + titlebar_transparent: None, + fullsize_content_view: None, + min_inner_size: None, + max_inner_size: None, + drag_and_drop: None, + close_button: None, + } + } pub fn with_title(mut self, title: impl Into) -> Self { self.title = title.into(); self } pub fn with_decorations(mut self, decorations: bool) -> Self { - self.decorations = decorations; + self.decorations = Some(decorations); self } pub fn with_fullscreen(mut self, fullscreen: bool) -> Self { - self.fullscreen = fullscreen; + self.fullscreen = Some(fullscreen); self } pub fn with_maximized(mut self, maximized: bool) -> Self { - self.maximized = maximized; + self.maximized = Some(maximized); self } pub fn with_resizable(mut self, resizable: bool) -> Self { - self.resizable = resizable; + self.resizable = Some(resizable); self } pub fn with_transparent(mut self, transparent: bool) -> Self { - self.transparent = transparent; + self.transparent = Some(transparent); self } - pub fn with_window_icon(mut self, icon: Option<(u32, u32, Vec)>) -> Self { - self.icon = icon; + /// The icon needs to be wraped in Arc because will be copyed every frame + pub fn with_window_icon(mut self, icon: Option)>>) -> Self { + self.icon = Some(icon); self } pub fn with_active(mut self, active: bool) -> Self { - self.active = active; + self.active = Some(active); self } pub fn with_visible(mut self, visible: bool) -> Self { - self.visible = visible; + self.visible = Some(visible); self } pub fn with_title_hidden(mut self, title_hidden: bool) -> Self { - self.title_hidden = title_hidden; + self.title_hidden = Some(title_hidden); self } pub fn with_titlebar_transparent(mut self, value: bool) -> Self { - self.titlebar_transparent = value; + self.titlebar_transparent = Some(value); self } pub fn with_fullsize_content_view(mut self, value: bool) -> Self { - self.fullsize_content_view = value; + self.fullsize_content_view = Some(value); self } - pub fn with_inner_size(mut self, value: (u32, u32)) -> Self { + pub fn with_inner_size(mut self, value: Option<(u32, u32)>) -> Self { self.inner_size = Some(value); self } - pub fn with_min_inner_size(mut self, value: (u32, u32)) -> Self { + pub fn with_min_inner_size(mut self, value: Option<(u32, u32)>) -> Self { self.min_inner_size = Some(value); self } - pub fn with_max_inner_size(mut self, value: (u32, u32)) -> Self { + pub fn with_max_inner_size(mut self, value: Option<(u32, u32)>) -> Self { self.max_inner_size = Some(value); self } - pub fn with_drag_and_drop(mut self, value: bool) -> Self { - self.drag_and_drop = value; + pub fn with_close_button(mut self, value: bool) -> Self { + self.close_button = Some(value); self } - pub fn with_position(mut self, value: (i32, i32)) -> Self { + pub fn with_drag_and_drop(mut self, value: bool) -> Self { + self.drag_and_drop = Some(value); + self + } + + pub fn with_position(mut self, value: Option<(i32, i32)>) -> Self { self.position = Some(value); self }