mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 14:50:03 -04:00
Is creating a window
This commit is contained in:
@@ -401,6 +401,7 @@ mod glow_integration {
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use egui::{epaint::ahash::HashMap, window::WindowBuilder, NumExt as _};
|
use egui::{epaint::ahash::HashMap, window::WindowBuilder, NumExt as _};
|
||||||
|
use glow::HasContext;
|
||||||
use glutin::{
|
use glutin::{
|
||||||
display::GetGlDisplay,
|
display::GetGlDisplay,
|
||||||
prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext},
|
prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext},
|
||||||
@@ -601,63 +602,76 @@ mod glow_integration {
|
|||||||
/// we presently assume that we will
|
/// we presently assume that we will
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn on_resume(&mut self, event_loop: &EventLoopWindowTarget<UserEvent>) -> Result<()> {
|
fn on_resume(&mut self, event_loop: &EventLoopWindowTarget<UserEvent>) -> Result<()> {
|
||||||
if self.windows[0].gl_surface.is_some() {
|
for win in self.windows.iter_mut() {
|
||||||
log::warn!("on_resume called even thought we already have a surface. early return");
|
if win.gl_surface.is_some() {
|
||||||
return Ok(());
|
continue;
|
||||||
|
}
|
||||||
|
log::debug!("running on_resume fn.");
|
||||||
|
// make sure we have a window or create one.
|
||||||
|
let window = win.window.take().unwrap_or_else(|| {
|
||||||
|
log::debug!("window doesn't exist yet. creating one now with finalize_window");
|
||||||
|
glutin_winit::finalize_window(
|
||||||
|
event_loop,
|
||||||
|
create_winit_window_builder(&win.builder),
|
||||||
|
&self.gl_config,
|
||||||
|
)
|
||||||
|
.expect("failed to finalize glutin window")
|
||||||
|
});
|
||||||
|
// surface attributes
|
||||||
|
let (width, height): (u32, u32) = window.inner_size().into();
|
||||||
|
let width = std::num::NonZeroU32::new(width.at_least(1)).unwrap();
|
||||||
|
let height = std::num::NonZeroU32::new(height.at_least(1)).unwrap();
|
||||||
|
let surface_attributes = glutin::surface::SurfaceAttributesBuilder::<
|
||||||
|
glutin::surface::WindowSurface,
|
||||||
|
>::new()
|
||||||
|
.build(window.raw_window_handle(), width, height);
|
||||||
|
log::debug!(
|
||||||
|
"creating surface with attributes: {:?}",
|
||||||
|
&surface_attributes
|
||||||
|
);
|
||||||
|
// create surface
|
||||||
|
let gl_surface = unsafe {
|
||||||
|
self.gl_config
|
||||||
|
.display()
|
||||||
|
.create_window_surface(&self.gl_config, &surface_attributes)?
|
||||||
|
};
|
||||||
|
log::debug!("surface created successfully: {gl_surface:?}.making context current");
|
||||||
|
// make surface and context current.
|
||||||
|
let not_current_gl_context =
|
||||||
|
if let Some(not_current_context) = self.not_current_gl_context.take() {
|
||||||
|
not_current_context
|
||||||
|
} else {
|
||||||
|
self.current_gl_context
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.make_not_current()
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
let current_gl_context = not_current_gl_context.make_current(&gl_surface)?;
|
||||||
|
// try setting swap interval. but its not absolutely necessary, so don't panic on failure.
|
||||||
|
log::debug!("made context current. setting swap interval for surface");
|
||||||
|
if let Err(e) =
|
||||||
|
gl_surface.set_swap_interval(¤t_gl_context, self.swap_interval)
|
||||||
|
{
|
||||||
|
log::error!("failed to set swap interval due to error: {e:?}");
|
||||||
|
}
|
||||||
|
// we will reach this point only once in most platforms except android.
|
||||||
|
// create window/surface/make context current once and just use them forever.
|
||||||
|
win.gl_surface = Some(gl_surface);
|
||||||
|
self.current_gl_context = Some(current_gl_context);
|
||||||
|
self.window_maps.insert(window.id(), win.window_id);
|
||||||
|
win.window = Some(window);
|
||||||
}
|
}
|
||||||
log::debug!("running on_resume fn.");
|
|
||||||
// make sure we have a window or create one.
|
|
||||||
let window = self.windows[0].window.take().unwrap_or_else(|| {
|
|
||||||
log::debug!("window doesn't exist yet. creating one now with finalize_window");
|
|
||||||
glutin_winit::finalize_window(
|
|
||||||
event_loop,
|
|
||||||
create_winit_window_builder(&self.windows[0].builder),
|
|
||||||
&self.gl_config,
|
|
||||||
)
|
|
||||||
.expect("failed to finalize glutin window")
|
|
||||||
});
|
|
||||||
// surface attributes
|
|
||||||
let (width, height): (u32, u32) = window.inner_size().into();
|
|
||||||
let width = std::num::NonZeroU32::new(width.at_least(1)).unwrap();
|
|
||||||
let height = std::num::NonZeroU32::new(height.at_least(1)).unwrap();
|
|
||||||
let surface_attributes =
|
|
||||||
glutin::surface::SurfaceAttributesBuilder::<glutin::surface::WindowSurface>::new()
|
|
||||||
.build(window.raw_window_handle(), width, height);
|
|
||||||
log::debug!(
|
|
||||||
"creating surface with attributes: {:?}",
|
|
||||||
&surface_attributes
|
|
||||||
);
|
|
||||||
// create surface
|
|
||||||
let gl_surface = unsafe {
|
|
||||||
self.gl_config
|
|
||||||
.display()
|
|
||||||
.create_window_surface(&self.gl_config, &surface_attributes)?
|
|
||||||
};
|
|
||||||
log::debug!("surface created successfully: {gl_surface:?}.making context current");
|
|
||||||
// make surface and context current.
|
|
||||||
let not_current_gl_context = self
|
|
||||||
.not_current_gl_context
|
|
||||||
.take()
|
|
||||||
.expect("failed to get not current context after resume event. impossible!");
|
|
||||||
let current_gl_context = not_current_gl_context.make_current(&gl_surface)?;
|
|
||||||
// try setting swap interval. but its not absolutely necessary, so don't panic on failure.
|
|
||||||
log::debug!("made context current. setting swap interval for surface");
|
|
||||||
if let Err(e) = gl_surface.set_swap_interval(¤t_gl_context, self.swap_interval) {
|
|
||||||
log::error!("failed to set swap interval due to error: {e:?}");
|
|
||||||
}
|
|
||||||
// we will reach this point only once in most platforms except android.
|
|
||||||
// create window/surface/make context current once and just use them forever.
|
|
||||||
self.windows[0].gl_surface = Some(gl_surface);
|
|
||||||
self.current_gl_context = Some(current_gl_context);
|
|
||||||
self.windows[0].window = Some(window);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// only applies for android. but we basically drop surface + window and make context not current
|
/// only applies for android. but we basically drop surface + window and make context not current
|
||||||
fn on_suspend(&mut self) -> Result<()> {
|
fn on_suspend(&mut self) -> Result<()> {
|
||||||
log::debug!("received suspend event. dropping window and surface");
|
log::debug!("received suspend event. dropping window and surface");
|
||||||
self.windows[0].gl_surface.take();
|
for window in self.windows.iter_mut() {
|
||||||
self.windows[0].window.take();
|
window.gl_surface.take();
|
||||||
|
window.window.take();
|
||||||
|
}
|
||||||
if let Some(current) = self.current_gl_context.take() {
|
if let Some(current) = self.current_gl_context.take() {
|
||||||
log::debug!("context is current, so making it non-current");
|
log::debug!("context is current, so making it non-current");
|
||||||
self.not_current_gl_context = Some(current.make_not_current()?);
|
self.not_current_gl_context = Some(current.make_not_current()?);
|
||||||
@@ -674,20 +688,31 @@ mod glow_integration {
|
|||||||
.expect("winit window doesn't exist")
|
.expect("winit window doesn't exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, physical_size: winit::dpi::PhysicalSize<u32>) {
|
fn resize(&mut self, window_id: u64, physical_size: winit::dpi::PhysicalSize<u32>) {
|
||||||
let width = std::num::NonZeroU32::new(physical_size.width.at_least(1)).unwrap();
|
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();
|
let height = std::num::NonZeroU32::new(physical_size.height.at_least(1)).unwrap();
|
||||||
self.windows[0]
|
for window in self.windows.iter_mut() {
|
||||||
.gl_surface
|
if window.window_id == window_id {
|
||||||
.as_ref()
|
if let Some(gl_surface) = &window.gl_surface {
|
||||||
.expect("failed to get surface to resize")
|
self.current_gl_context = Some(
|
||||||
.resize(
|
self.current_gl_context
|
||||||
self.current_gl_context
|
.take()
|
||||||
.as_ref()
|
.unwrap()
|
||||||
.expect("failed to get current context to resize surface"),
|
.make_not_current()
|
||||||
width,
|
.unwrap()
|
||||||
height,
|
.make_current(&gl_surface)
|
||||||
);
|
.unwrap(),
|
||||||
|
);
|
||||||
|
gl_surface.resize(
|
||||||
|
self.current_gl_context
|
||||||
|
.as_ref()
|
||||||
|
.expect("failed to get current context to resize surface"),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swap_buffers(&self) -> glutin::error::Result<()> {
|
fn swap_buffers(&self) -> glutin::error::Result<()> {
|
||||||
@@ -958,7 +983,20 @@ mod glow_integration {
|
|||||||
|
|
||||||
let control_flow;
|
let control_flow;
|
||||||
{
|
{
|
||||||
let window = gl_window.window(window_index);
|
// let window = gl_window.window(window_index);
|
||||||
|
let win: Option<&Window> = gl_window.windows.get(window_index);
|
||||||
|
let win = win.unwrap();
|
||||||
|
let window = win.window.as_ref().unwrap();
|
||||||
|
gl_window.current_gl_context = Some(
|
||||||
|
gl_window
|
||||||
|
.current_gl_context
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.make_not_current()
|
||||||
|
.unwrap()
|
||||||
|
.make_current(win.gl_surface.as_ref().unwrap())
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
let screen_size_in_pixels: [u32; 2] = window.inner_size().into();
|
let screen_size_in_pixels: [u32; 2] = window.inner_size().into();
|
||||||
|
|
||||||
@@ -1104,6 +1142,7 @@ mod glow_integration {
|
|||||||
window: None,
|
window: None,
|
||||||
window_id: id,
|
window_id: id,
|
||||||
});
|
});
|
||||||
|
wins.push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_window.windows.retain(|w| wins.contains(&w.window_id));
|
gl_window.windows.retain(|w| wins.contains(&w.window_id));
|
||||||
@@ -1170,6 +1209,13 @@ mod glow_integration {
|
|||||||
EventResult::Wait
|
EventResult::Wait
|
||||||
}
|
}
|
||||||
|
|
||||||
|
winit::event::Event::MainEventsCleared => {
|
||||||
|
if let Some(running) = self.running.as_mut() {
|
||||||
|
running.gl_window.on_resume(event_loop);
|
||||||
|
}
|
||||||
|
EventResult::Wait
|
||||||
|
}
|
||||||
|
|
||||||
winit::event::Event::WindowEvent { event, window_id } => {
|
winit::event::Event::WindowEvent { event, window_id } => {
|
||||||
if let Some(running) = &mut self.running {
|
if let Some(running) = &mut self.running {
|
||||||
// On Windows, if a window is resized by the user, it should repaint synchronously, inside the
|
// On Windows, if a window is resized by the user, it should repaint synchronously, inside the
|
||||||
@@ -1198,7 +1244,9 @@ mod glow_integration {
|
|||||||
// See: https://github.com/rust-windowing/winit/issues/208
|
// See: https://github.com/rust-windowing/winit/issues/208
|
||||||
// This solves an issue where the app would panic when minimizing on Windows.
|
// This solves an issue where the app would panic when minimizing on Windows.
|
||||||
if physical_size.width > 0 && physical_size.height > 0 {
|
if physical_size.width > 0 && physical_size.height > 0 {
|
||||||
running.gl_window.resize(*physical_size);
|
if let Some(id) = running.gl_window.window_maps.get(window_id) {
|
||||||
|
running.gl_window.resize(*id, *physical_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
winit::event::WindowEvent::ScaleFactorChanged {
|
winit::event::WindowEvent::ScaleFactorChanged {
|
||||||
@@ -1206,7 +1254,9 @@ mod glow_integration {
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
repaint_asap = true;
|
repaint_asap = true;
|
||||||
running.gl_window.resize(**new_inner_size);
|
if let Some(id) = running.gl_window.window_maps.get(window_id) {
|
||||||
|
running.gl_window.resize(*id, **new_inner_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
winit::event::WindowEvent::CloseRequested
|
winit::event::WindowEvent::CloseRequested
|
||||||
if running.integration.should_close() =>
|
if running.integration.should_close() =>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use epaint::*;
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Clone, Default)]
|
#[derive(Hash, PartialEq, Clone)]
|
||||||
pub struct WindowBuilder {
|
pub struct WindowBuilder {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
@@ -28,6 +28,31 @@ pub struct WindowBuilder {
|
|||||||
pub drag_and_drop: bool,
|
pub drag_and_drop: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for WindowBuilder {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
title: "Dummy EGUI Window".into(),
|
||||||
|
name: None,
|
||||||
|
position: None,
|
||||||
|
inner_size: Some((600, 500)),
|
||||||
|
fullscreen: false,
|
||||||
|
maximized: false,
|
||||||
|
resizable: true,
|
||||||
|
transparent: false,
|
||||||
|
decorations: true,
|
||||||
|
icon: None,
|
||||||
|
active: true,
|
||||||
|
visible: true,
|
||||||
|
title_hidden: false,
|
||||||
|
titlebar_transparent: false,
|
||||||
|
fullsize_content_view: false,
|
||||||
|
min_inner_size: None,
|
||||||
|
max_inner_size: None,
|
||||||
|
drag_and_drop: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WindowBuilder {
|
impl WindowBuilder {
|
||||||
pub fn with_title(mut self, title: impl Into<String>) -> Self {
|
pub fn with_title(mut self, title: impl Into<String>) -> Self {
|
||||||
self.title = title.into();
|
self.title = title.into();
|
||||||
@@ -396,8 +421,8 @@ impl<'open> Window<'open> {
|
|||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||||
) -> Option<InnerResponse<Option<R>>> {
|
) -> Option<InnerResponse<Option<R>>> {
|
||||||
let window_id =
|
let window_id = ctx.create_window(WindowBuilder::default().with_title(self.title.text()));
|
||||||
ctx.data_mut(|data| *data.get_temp_mut_or(self.area.id.with("window_id"), 0));
|
println!("Window id: {}", window_id);
|
||||||
let Window {
|
let Window {
|
||||||
title,
|
title,
|
||||||
open,
|
open,
|
||||||
|
|||||||
@@ -1268,10 +1268,10 @@ impl Context {
|
|||||||
let repaint_after = self.write(|ctx| ctx.repaint.end_frame());
|
let repaint_after = self.write(|ctx| ctx.repaint.end_frame());
|
||||||
let shapes = self.drain_paint_lists();
|
let shapes = self.drain_paint_lists();
|
||||||
|
|
||||||
let windows = self.write(|ctx| {
|
let windows = self.read(|ctx| {
|
||||||
ctx.windows
|
ctx.windows
|
||||||
.drain()
|
.iter()
|
||||||
.map(|(_, (builder, id, _))| (id, builder))
|
.map(|(_, (builder, id, _))| (*id, builder.clone()))
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ fn main() -> Result<(), eframe::Error> {
|
|||||||
age += 1;
|
age += 1;
|
||||||
}
|
}
|
||||||
ui.label(format!("Hello '{name}', age {age}"));
|
ui.label(format!("Hello '{name}', age {age}"));
|
||||||
|
egui::CollapsingHeader::new("W").show(ui, |ui| {
|
||||||
|
egui::Window::new("Win").show(ctx, |ui| ui.label("Inside a window!"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user