1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 13:20:05 -04:00

Get hello world simple to compile

This commit is contained in:
lucasmerlin
2025-11-19 12:14:08 +01:00
parent 7980401b25
commit e285050abc
25 changed files with 1016 additions and 766 deletions

View File

@@ -140,7 +140,8 @@ serde = { workspace = true, optional = true }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
egui-winit = { workspace = true, default-features = false, features = ["clipboard", "links"] }
image = { workspace = true, features = ["png"] } # Needed for app icon
winit = { workspace = true, default-features = false, features = ["rwh_06"] }
winit = { workspace = true, default-features = false }
winit-core.workspace = true
# optional native:
egui-wgpu = { workspace = true, optional = true, features = [
@@ -169,7 +170,10 @@ objc2-foundation = { workspace = true, default-features = false, features = [
objc2-app-kit = { workspace = true, default-features = false, features = [
"std",
"NSApplication",
"NSBitmapImageRep",
"NSGraphics",
"NSImage",
"NSImageRep",
"NSMenu",
"NSMenuItem",
"NSResponder",

View File

@@ -31,7 +31,7 @@ pub use winit::{event_loop::EventLoopBuilder, window::WindowAttributes};
/// done by `EFrame`.
#[cfg(not(target_arch = "wasm32"))]
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
pub type EventLoopBuilderHook = Box<dyn FnOnce(&mut EventLoopBuilder<UserEvent>)>;
pub type EventLoopBuilderHook = Box<dyn FnOnce(&mut EventLoopBuilder)>;
/// Hook into the building of a the native window.
///

View File

@@ -327,7 +327,7 @@ pub fn create_native<'a>(
app_name: &str,
mut native_options: NativeOptions,
app_creator: AppCreator<'a>,
event_loop: &winit::event_loop::EventLoop<UserEvent>,
event_loop: &winit::event_loop::EventLoop,
) -> EframeWinitApplication<'a> {
let renderer = init_native(app_name, &mut native_options);
@@ -455,6 +455,10 @@ pub enum Error {
#[cfg(not(target_arch = "wasm32"))]
Winit(winit::error::OsError),
/// An request error from [`winit`].
#[cfg(not(target_arch = "wasm32"))]
WinitRequest(winit::error::RequestError),
/// An error from [`winit::event_loop::EventLoop`].
#[cfg(not(target_arch = "wasm32"))]
WinitEventLoop(winit::error::EventLoopError),
@@ -486,6 +490,14 @@ impl From<winit::error::OsError> for Error {
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<winit::error::RequestError> for Error {
#[inline]
fn from(err: winit::error::RequestError) -> Self {
Self::WinitRequest(err)
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<winit::error::EventLoopError> for Error {
#[inline]
@@ -555,6 +567,9 @@ impl std::fmt::Display for Error {
Self::Wgpu(err) => {
write!(f, "WGPU error: {err}")
}
Error::WinitRequest(err) => {
write!(f, "winit request error: {err}")
}
}
}
}

View File

@@ -15,7 +15,7 @@ use crate::epi;
#[cfg_attr(target_os = "ios", allow(dead_code, unused_variables, unused_mut))]
pub fn viewport_builder(
egui_zoom_factor: f32,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
native_options: &mut epi::NativeOptions,
window_settings: Option<WindowSettings>,
) -> ViewportBuilder {
@@ -71,15 +71,16 @@ pub fn viewport_builder(
.primary_monitor()
.or_else(|| event_loop.available_monitors().next())
{
let monitor_size = monitor
.size()
.to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
let inner_size = inner_size_points.unwrap_or(egui::Vec2 { x: 800.0, y: 600.0 });
if 0.0 < monitor_size.width && 0.0 < monitor_size.height {
let x = (monitor_size.width - inner_size.x) / 2.0;
let y = (monitor_size.height - inner_size.y) / 2.0;
viewport_builder = viewport_builder.with_position([x, y]);
}
todo!()
// let monitor_size = monitor
// .size()
// .to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
// let inner_size = inner_size_points.unwrap_or(egui::Vec2 { x: 800.0, y: 600.0 });
// if 0.0 < monitor_size.width && 0.0 < monitor_size.height {
// let x = (monitor_size.width - inner_size.x) / 2.0;
// let y = (monitor_size.height - inner_size.y) / 2.0;
// viewport_builder = viewport_builder.with_position([x, y]);
// }
}
}
@@ -90,7 +91,7 @@ pub fn viewport_builder(
}
pub fn apply_window_settings(
window: &winit::window::Window,
window: &dyn winit::window::Window,
window_settings: Option<WindowSettings>,
) {
profiling::function_scope!();
@@ -100,7 +101,7 @@ pub fn apply_window_settings(
}
#[cfg(not(target_os = "ios"))]
fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &ActiveEventLoop) -> egui::Vec2 {
fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &dyn ActiveEventLoop) -> egui::Vec2 {
profiling::function_scope!();
let mut max_size = egui::Vec2::ZERO;
@@ -110,11 +111,12 @@ fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &ActiveEventLoo
};
for monitor in available_monitors {
let size = monitor
.size()
.to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
let size = egui::vec2(size.width, size.height);
max_size = max_size.max(size);
todo!()
// let size = monitor
// .size()
// .to_logical::<f32>(egui_zoom_factor as f64 * monitor.scale_factor());
// let size = egui::vec2(size.width, size.height);
// max_size = max_size.max(size);
}
if max_size == egui::Vec2::ZERO {
@@ -171,7 +173,7 @@ impl EpiIntegration {
#[allow(clippy::allow_attributes, clippy::too_many_arguments)]
pub fn new(
egui_ctx: egui::Context,
window: &winit::window::Window,
window: &dyn winit::window::Window,
app_name: &str,
native_options: &crate::NativeOptions,
storage: Option<Box<dyn epi::Storage>>,
@@ -233,7 +235,7 @@ impl EpiIntegration {
pub fn on_window_event(
&mut self,
window: &winit::window::Window,
window: &dyn winit::window::Window,
egui_winit: &mut egui_winit::State,
event: &winit::event::WindowEvent,
) -> EventResponse {
@@ -241,14 +243,15 @@ impl EpiIntegration {
use winit::event::{ElementState, MouseButton, WindowEvent};
if let WindowEvent::MouseInput {
button: MouseButton::Left,
state: ElementState::Pressed,
..
} = event
{
self.can_drag_window = true;
}
// TODO
// if let WindowEvent::MouseInput {
// button: MouseButton::Left,
// state: ElementState::Pressed,
// ..
// } = event
// {
// self.can_drag_window = true;
// }
egui_winit.on_window_event(window, event)
}
@@ -304,7 +307,7 @@ impl EpiIntegration {
self.frame.info.cpu_usage = Some(seconds);
}
pub fn post_rendering(&mut self, window: &winit::window::Window) {
pub fn post_rendering(&mut self, window: &dyn winit::window::Window) {
profiling::function_scope!();
if std::mem::take(&mut self.is_first_frame) {
// We keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279
@@ -318,7 +321,7 @@ impl EpiIntegration {
pub fn maybe_autosave(
&mut self,
app: &mut dyn epi::App,
window: Option<&winit::window::Window>,
window: Option<&dyn winit::window::Window>,
) {
let now = Instant::now();
if now - self.last_auto_save > app.auto_save_interval() {
@@ -327,7 +330,7 @@ impl EpiIntegration {
}
}
pub fn save(&mut self, app: &mut dyn epi::App, window: Option<&winit::window::Window>) {
pub fn save(&mut self, app: &mut dyn epi::App, window: Option<&dyn winit::window::Window>) {
#[cfg(not(feature = "persistence"))]
let _ = (self, app, window);

View File

@@ -2,19 +2,19 @@ use std::cell::Cell;
use winit::event_loop::ActiveEventLoop;
thread_local! {
static CURRENT_EVENT_LOOP: Cell<Option<*const ActiveEventLoop>> = const { Cell::new(None) };
static CURRENT_EVENT_LOOP: Cell<Option<*const dyn ActiveEventLoop>> = const { Cell::new(None) };
}
struct EventLoopGuard;
impl EventLoopGuard {
fn new(event_loop: &ActiveEventLoop) -> Self {
fn new(event_loop: &dyn ActiveEventLoop) -> Self {
CURRENT_EVENT_LOOP.with(|cell| {
assert!(
cell.get().is_none(),
"Attempted to set a new event loop while one is already set"
);
cell.set(Some(std::ptr::from_ref::<ActiveEventLoop>(event_loop)));
cell.set(Some(std::ptr::from_ref::<dyn ActiveEventLoop>(event_loop)));
});
Self
}
@@ -30,7 +30,7 @@ impl Drop for EventLoopGuard {
#[expect(unsafe_code)]
pub fn with_current_event_loop<F, R>(f: F) -> Option<R>
where
F: FnOnce(&ActiveEventLoop) -> R,
F: FnOnce(&dyn ActiveEventLoop) -> R,
{
CURRENT_EVENT_LOOP.with(|cell| {
cell.get().map(|ptr| {
@@ -47,7 +47,7 @@ where
}
// The only public interface to use the event loop
pub fn with_event_loop_context(event_loop: &ActiveEventLoop, f: impl FnOnce()) {
pub fn with_event_loop_context(event_loop: &dyn ActiveEventLoop, f: impl FnOnce()) {
// NOTE: For safety, this guard must NOT be leaked.
let _guard = EventLoopGuard::new(event_loop);
f();

View File

@@ -15,12 +15,12 @@ use crate::{
};
// ----------------------------------------------------------------------------
fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result<EventLoop<UserEvent>> {
fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result<EventLoop> {
#[cfg(target_os = "android")]
use winit::platform::android::EventLoopBuilderExtAndroid as _;
profiling::function_scope!();
let mut builder = winit::event_loop::EventLoop::with_user_event();
let mut builder = winit::event_loop::EventLoop::builder();
#[cfg(target_os = "android")]
let mut builder =
@@ -45,9 +45,9 @@ fn create_event_loop(native_options: &mut epi::NativeOptions) -> Result<EventLoo
#[cfg(not(target_os = "ios"))]
fn with_event_loop<R>(
mut native_options: epi::NativeOptions,
f: impl FnOnce(&mut EventLoop<UserEvent>, epi::NativeOptions) -> R,
f: impl FnOnce(&mut EventLoop, epi::NativeOptions) -> R,
) -> Result<R> {
thread_local!(static EVENT_LOOP: std::cell::RefCell<Option<EventLoop<UserEvent>>> = const { std::cell::RefCell::new(None) });
thread_local!(static EVENT_LOOP: std::cell::RefCell<Option<EventLoop>> = const { std::cell::RefCell::new(None) });
EVENT_LOOP.with(|event_loop| {
// Since we want to reference NativeOptions when creating the EventLoop we can't
@@ -84,7 +84,7 @@ impl<T: WinitApp> WinitAppWrapper<T> {
fn handle_event_result(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
event_result: Result<EventResult>,
) {
let mut exit = false;
@@ -174,7 +174,7 @@ impl<T: WinitApp> WinitAppWrapper<T> {
self.check_redraw_requests(event_loop);
}
fn check_redraw_requests(&mut self, event_loop: &ActiveEventLoop) {
fn check_redraw_requests(&mut self, event_loop: &dyn ActiveEventLoop) {
let now = Instant::now();
self.windows_next_repaint_times
@@ -201,8 +201,8 @@ impl<T: WinitApp> WinitAppWrapper<T> {
}
}
impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
impl<T: WinitApp> ApplicationHandler for WinitAppWrapper<T> {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
profiling::scope!("Event::Suspended");
event_loop_context::with_event_loop_context(event_loop, move || {
@@ -211,7 +211,7 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
});
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
profiling::scope!("Event::Resumed");
// Nb: Make sure this guard is dropped after this function returns.
@@ -221,19 +221,19 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
});
}
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
// On Mac, Cmd-Q we get here and then `run_app_on_demand` doesn't return (despite its name),
// so we need to save state now:
log::debug!("Received Event::LoopExiting - saving app state…");
event_loop_context::with_event_loop_context(event_loop, move || {
self.winit_app.save_and_destroy();
});
}
// fn exiting(&mut self, event_loop: &ActiveEventLoop) {
// // On Mac, Cmd-Q we get here and then `run_app_on_demand` doesn't return (despite its name),
// // so we need to save state now:
// log::debug!("Received Event::LoopExiting - saving app state…");
// event_loop_context::with_event_loop_context(event_loop, move || {
// self.winit_app.save_and_destroy();
// });
// }
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
device_id: winit::event::DeviceId,
event_loop: &dyn ActiveEventLoop,
device_id: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) {
profiling::function_scope!(egui_winit::short_device_event_description(&event));
@@ -245,50 +245,51 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
});
}
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
profiling::function_scope!(match &event {
UserEvent::RequestRepaint { .. } => "UserEvent::RequestRepaint",
#[cfg(feature = "accesskit")]
UserEvent::AccessKitActionRequest(_) => "UserEvent::AccessKitActionRequest",
});
// TODO: User event handling?
// fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
// profiling::function_scope!(match &event {
// UserEvent::RequestRepaint { .. } => "UserEvent::RequestRepaint",
// #[cfg(feature = "accesskit")]
// UserEvent::AccessKitActionRequest(_) => "UserEvent::AccessKitActionRequest",
// });
//
// event_loop_context::with_event_loop_context(event_loop, move || {
// let event_result = match event {
// UserEvent::RequestRepaint {
// when,
// cumulative_pass_nr,
// viewport_id,
// } => {
// let current_pass_nr = self
// .winit_app
// .egui_ctx()
// .map_or(0, |ctx| ctx.cumulative_pass_nr_for(viewport_id));
// if current_pass_nr == cumulative_pass_nr
// || current_pass_nr == cumulative_pass_nr + 1
// {
// log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
// if let Some(window_id) =
// self.winit_app.window_id_from_viewport_id(viewport_id)
// {
// Ok(EventResult::RepaintAt(window_id, when))
// } else {
// Ok(EventResult::Wait)
// }
// } else {
// log::trace!("Got outdated UserEvent::RequestRepaint");
// Ok(EventResult::Wait) // old request - we've already repainted
// }
// }
// #[cfg(feature = "accesskit")]
// UserEvent::AccessKitActionRequest(request) => {
// self.winit_app.on_accesskit_event(request)
// }
// };
// self.handle_event_result(event_loop, event_result);
// });
// }
event_loop_context::with_event_loop_context(event_loop, move || {
let event_result = match event {
UserEvent::RequestRepaint {
when,
cumulative_pass_nr,
viewport_id,
} => {
let current_pass_nr = self
.winit_app
.egui_ctx()
.map_or(0, |ctx| ctx.cumulative_pass_nr_for(viewport_id));
if current_pass_nr == cumulative_pass_nr
|| current_pass_nr == cumulative_pass_nr + 1
{
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
if let Some(window_id) =
self.winit_app.window_id_from_viewport_id(viewport_id)
{
Ok(EventResult::RepaintAt(window_id, when))
} else {
Ok(EventResult::Wait)
}
} else {
log::trace!("Got outdated UserEvent::RequestRepaint");
Ok(EventResult::Wait) // old request - we've already repainted
}
}
#[cfg(feature = "accesskit")]
UserEvent::AccessKitActionRequest(request) => {
self.winit_app.on_accesskit_event(request)
}
};
self.handle_event_result(event_loop, event_result);
});
}
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: winit::event::StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
if let winit::event::StartCause::ResumeTimeReached { .. } = cause {
log::trace!("Woke up to check next_repaint_time");
}
@@ -298,7 +299,7 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) {
@@ -316,11 +317,15 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
self.handle_event_result(event_loop, event_result);
});
}
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
}
}
#[cfg(not(target_os = "ios"))]
fn run_and_return(event_loop: &mut EventLoop<UserEvent>, winit_app: impl WinitApp) -> Result {
use winit::platform::run_on_demand::EventLoopExtRunOnDemand as _;
fn run_and_return(event_loop: &mut EventLoop, winit_app: impl WinitApp) -> Result {
use winit_core::event_loop::run_on_demand::EventLoopExtRunOnDemand as _;
log::trace!("Entering the winit event loop (run_app_on_demand)…");
@@ -330,12 +335,16 @@ fn run_and_return(event_loop: &mut EventLoop<UserEvent>, winit_app: impl WinitAp
app.return_result
}
fn run_and_exit(event_loop: EventLoop<UserEvent>, winit_app: impl WinitApp) -> Result {
fn run_and_exit(event_loop: EventLoop, winit_app: impl WinitApp) -> Result {
log::trace!("Entering the winit event loop (run_app)…");
// When to repaint what window
let mut app = WinitAppWrapper::new(winit_app, false);
event_loop.run_app(&mut app)?;
// let mut app = Box::leak(Box::new(app)); // TODO: avoid leak
let app_mut: &mut dyn ApplicationHandler = &mut app;
#[allow(unsafe_code)]
let app_mut: &'static mut dyn ApplicationHandler = unsafe { std::mem::transmute(app_mut) }; // TODO: avoid unsafe
event_loop.run_app(app_mut)?;
log::debug!("winit event loop unexpectedly returned");
Ok(())
@@ -371,8 +380,8 @@ pub fn create_glow<'a>(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'a>,
event_loop: &EventLoop<UserEvent>,
) -> impl ApplicationHandler<UserEvent> + 'a {
event_loop: &EventLoop,
) -> impl ApplicationHandler + 'a {
use super::glow_integration::GlowWinitApp;
let glow_eframe = GlowWinitApp::new(event_loop, app_name, native_options, app_creator);
@@ -409,8 +418,8 @@ pub fn create_wgpu<'a>(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'a>,
event_loop: &EventLoop<UserEvent>,
) -> impl ApplicationHandler<UserEvent> + 'a {
event_loop: &EventLoop,
) -> impl ApplicationHandler + 'a {
use super::wgpu_integration::WgpuWinitApp;
let wgpu_eframe = WgpuWinitApp::new(event_loop, app_name, native_options, app_creator);
@@ -424,61 +433,65 @@ pub fn create_wgpu<'a>(
/// This can be run directly on your own [`EventLoop`] by itself or with other
/// windows you manage outside of eframe.
pub struct EframeWinitApplication<'a> {
wrapper: Box<dyn ApplicationHandler<UserEvent> + 'a>,
wrapper: Box<dyn ApplicationHandler + 'a>,
control_flow: ControlFlow,
}
impl ApplicationHandler<UserEvent> for EframeWinitApplication<'_> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
impl ApplicationHandler for EframeWinitApplication<'_> {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.resumed(event_loop);
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
self.wrapper.window_event(event_loop, window_id, event);
}
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: winit::event::StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
self.wrapper.new_events(event_loop, cause);
}
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
self.wrapper.user_event(event_loop, event);
}
// fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
// self.wrapper.user_event(event_loop, event);
// }
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
device_id: winit::event::DeviceId,
event_loop: &dyn ActiveEventLoop,
device_id: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) {
self.wrapper.device_event(event_loop, device_id, event);
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.about_to_wait(event_loop);
self.control_flow = event_loop.control_flow();
}
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.suspended(event_loop);
}
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
self.wrapper.exiting(event_loop);
// fn exiting(&mut self, event_loop: &ActiveEventLoop) {
// self.wrapper.exiting(event_loop);
// }
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
self.wrapper.memory_warning(event_loop);
}
fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
self.wrapper.memory_warning(event_loop);
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
todo!()
}
}
impl<'a> EframeWinitApplication<'a> {
pub(crate) fn new<T: ApplicationHandler<UserEvent> + 'a>(app: T) -> Self {
pub(crate) fn new<T: ApplicationHandler + 'a>(app: T) -> Self {
Self {
wrapper: Box::new(app),
control_flow: ControlFlow::default(),
@@ -495,12 +508,12 @@ impl<'a> EframeWinitApplication<'a> {
#[cfg(not(target_os = "ios"))]
pub fn pump_eframe_app(
&mut self,
event_loop: &mut EventLoop<UserEvent>,
event_loop: &mut EventLoop,
timeout: Option<std::time::Duration>,
) -> EframePumpStatus {
use winit::platform::pump_events::{EventLoopExtPumpEvents as _, PumpStatus};
use winit_core::event_loop::pump_events::{EventLoopExtPumpEvents as _, PumpStatus};
match event_loop.pump_app_events(timeout, self) {
match event_loop.pump_app_events(timeout, &mut *self) {
PumpStatus::Continue => EframePumpStatus::Continue(self.control_flow),
PumpStatus::Exit(code) => EframePumpStatus::Exit(code),
}

View File

@@ -6,7 +6,7 @@
//! like removing a bunch of `unwraps`.
use std::{cell::RefCell, num::NonZeroU32, rc::Rc, sync::Arc, time::Instant};
use std::ops::Deref;
use egui_winit::ActionRequested;
use parking_lot::Mutex;
use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};
@@ -36,7 +36,7 @@ use super::{epi_integration, event_loop_context, winit_integration, winit_integr
// Types:
pub struct WgpuWinitApp<'app> {
repaint_proxy: Arc<Mutex<EventLoopProxy<UserEvent>>>,
repaint_proxy: Arc<Mutex<EventLoopProxy>>,
app_name: String,
native_options: NativeOptions,
@@ -89,7 +89,7 @@ pub struct Viewport {
/// 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.
window: Option<Arc<Window>>,
window: Option<Arc<dyn Window>>,
/// `window` and `egui_winit` are initialized together.
egui_winit: Option<egui_winit::State>,
@@ -99,7 +99,7 @@ pub struct Viewport {
impl<'app> WgpuWinitApp<'app> {
pub fn new(
event_loop: &EventLoop<UserEvent>,
event_loop: &EventLoop,
app_name: &str,
native_options: NativeOptions,
app_creator: AppCreator<'app>,
@@ -122,7 +122,7 @@ impl<'app> WgpuWinitApp<'app> {
}
/// Create a window for all viewports lacking one.
fn initialized_all_windows(&mut self, event_loop: &ActiveEventLoop) {
fn initialized_all_windows(&mut self, event_loop: &dyn ActiveEventLoop) {
let Some(running) = &mut self.running else {
return;
};
@@ -178,9 +178,9 @@ impl<'app> WgpuWinitApp<'app> {
fn init_run_state(
&mut self,
egui_ctx: egui::Context,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
storage: Option<Box<dyn Storage>>,
window: Window,
window: Box<dyn Window>,
builder: ViewportBuilder,
) -> crate::Result<&mut WgpuWinitRunning<'app>> {
profiling::function_scope!();
@@ -200,12 +200,12 @@ impl<'app> WgpuWinitApp<'app> {
));
let mut viewport_info = ViewportInfo::default();
egui_winit::update_viewport_info(&mut viewport_info, &egui_ctx, &window, true);
egui_winit::update_viewport_info(&mut viewport_info, &egui_ctx, window.deref(), true);
{
// Tell egui right away about native_pixels_per_point etc,
// so that the app knows about it during app creation:
let pixels_per_point = egui_winit::pixels_per_point(&egui_ctx, &window);
let pixels_per_point = egui_winit::pixels_per_point(&egui_ctx, window.deref());
egui_ctx.input_mut(|i| {
i.raw
@@ -215,7 +215,7 @@ impl<'app> WgpuWinitApp<'app> {
});
}
let window = Arc::new(window);
let window: Arc<dyn Window> = Arc::from(window);
{
profiling::scope!("set_window");
@@ -226,7 +226,7 @@ impl<'app> WgpuWinitApp<'app> {
let integration = EpiIntegration::new(
egui_ctx.clone(),
&window,
window.deref(),
&self.app_name,
&self.native_options,
storage,
@@ -247,12 +247,14 @@ impl<'app> WgpuWinitApp<'app> {
event_loop_proxy
.lock()
.send_event(UserEvent::RequestRepaint {
when,
cumulative_pass_nr,
viewport_id: info.viewport_id,
})
.ok();
.wake_up();
// TODO: Pass user info somehow
// .send_event(UserEvent::RequestRepaint {
// when,
// cumulative_pass_nr,
// viewport_id: info.viewport_id,
// })
// .ok();
});
}
@@ -260,7 +262,7 @@ impl<'app> WgpuWinitApp<'app> {
let mut egui_winit = egui_winit::State::new(
egui_ctx.clone(),
ViewportId::ROOT,
event_loop,
&event_loop,
Some(window.scale_factor() as f32),
event_loop.system_theme(),
painter.max_texture_side(),
@@ -346,7 +348,7 @@ impl WinitApp for WgpuWinitApp<'_> {
self.running.as_ref().map(|r| &r.integration.egui_ctx)
}
fn window(&self, window_id: WindowId) -> Option<Arc<Window>> {
fn window(&self, window_id: WindowId) -> Option<Arc<dyn Window>> {
self.running
.as_ref()
.and_then(|r| {
@@ -386,7 +388,7 @@ impl WinitApp for WgpuWinitApp<'_> {
fn run_ui_and_paint(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
) -> Result<EventResult> {
self.initialized_all_windows(event_loop);
@@ -398,7 +400,7 @@ impl WinitApp for WgpuWinitApp<'_> {
}
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) -> crate::Result<EventResult> {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) -> crate::Result<EventResult> {
log::debug!("Event::Resumed");
let running = if let Some(running) = &self.running {
@@ -435,7 +437,7 @@ impl WinitApp for WgpuWinitApp<'_> {
}
}
fn suspended(&mut self, _: &ActiveEventLoop) -> crate::Result<EventResult> {
fn suspended(&mut self, _: &dyn ActiveEventLoop) -> crate::Result<EventResult> {
#[cfg(target_os = "android")]
self.drop_window()?;
Ok(EventResult::Save)
@@ -443,34 +445,35 @@ impl WinitApp for WgpuWinitApp<'_> {
fn device_event(
&mut self,
_: &ActiveEventLoop,
_: winit::event::DeviceId,
_: &dyn ActiveEventLoop,
_: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) -> crate::Result<EventResult> {
if let winit::event::DeviceEvent::MouseMotion { delta } = event
&& let Some(running) = &mut self.running
{
let mut shared = running.shared.borrow_mut();
if let Some(viewport) = shared
.focused_viewport
.and_then(|viewport| shared.viewports.get_mut(&viewport))
{
if let Some(egui_winit) = viewport.egui_winit.as_mut() {
egui_winit.on_mouse_motion(delta);
}
if let Some(window) = viewport.window.as_ref() {
return Ok(EventResult::RepaintNext(window.id()));
}
}
}
// TODO
// if let winit::event::DeviceEvent::MouseMotion { delta } = event
// && let Some(running) = &mut self.running
// {
// let mut shared = running.shared.borrow_mut();
// if let Some(viewport) = shared
// .focused_viewport
// .and_then(|viewport| shared.viewports.get_mut(&viewport))
// {
// if let Some(egui_winit) = viewport.egui_winit.as_mut() {
// egui_winit.on_mouse_motion(delta);
// }
//
// if let Some(window) = viewport.window.as_ref() {
// return Ok(EventResult::RepaintNext(window.id()));
// }
// }
// }
Ok(EventResult::Wait)
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) -> crate::Result<EventResult> {
@@ -606,7 +609,7 @@ impl WgpuWinitRunning<'_> {
let Some(window) = window else {
return Ok(EventResult::Wait);
};
egui_winit::update_viewport_info(info, &integration.egui_ctx, window, false);
egui_winit::update_viewport_info(info, &integration.egui_ctx, window.deref().deref(), false);
{
profiling::scope!("set_window");
@@ -616,7 +619,7 @@ impl WgpuWinitRunning<'_> {
let Some(egui_winit) = egui_winit.as_mut() else {
return Ok(EventResult::Wait);
};
let mut raw_input = egui_winit.take_egui_input(window);
let mut raw_input = egui_winit.take_egui_input(window.deref().deref());
integration.pre_update();
@@ -674,7 +677,7 @@ impl WgpuWinitRunning<'_> {
return Ok(EventResult::Wait);
};
egui_winit.handle_platform_output(window, platform_output);
egui_winit.handle_platform_output(&**window, platform_output);
let clipped_primitives = egui_ctx.tessellate(shapes, pixels_per_point);
@@ -721,7 +724,7 @@ impl WgpuWinitRunning<'_> {
}
}
integration.post_rendering(window);
integration.post_rendering(&**window);
let active_viewports_ids: ViewportIdSet = viewport_output.keys().copied().collect();
@@ -824,24 +827,25 @@ impl WgpuWinitRunning<'_> {
shared.focused_viewport = focused.then_some(viewport_id).flatten();
}
winit::event::WindowEvent::Resized(physical_size) => {
// Resize with 0 width and height is used by winit to signal a minimize event on Windows.
// See: https://github.com/rust-windowing/winit/issues/208
// This solves an issue where the app would panic when minimizing on Windows.
if let Some(id) = viewport_id
&& let (Some(width), Some(height)) = (
NonZeroU32::new(physical_size.width),
NonZeroU32::new(physical_size.height),
)
{
if shared.resized_viewport != viewport_id {
shared.resized_viewport = viewport_id;
shared.painter.on_window_resize_state_change(id, true);
}
shared.painter.on_window_resized(id, width, height);
repaint_asap = true;
}
}
// TODO
// winit::event::WindowEvent::Resized(physical_size) => {
// // Resize with 0 width and height is used by winit to signal a minimize event on Windows.
// // See: https://github.com/rust-windowing/winit/issues/208
// // This solves an issue where the app would panic when minimizing on Windows.
// if let Some(id) = viewport_id
// && let (Some(width), Some(height)) = (
// NonZeroU32::new(physical_size.width),
// NonZeroU32::new(physical_size.height),
// )
// {
// if shared.resized_viewport != viewport_id {
// shared.resized_viewport = viewport_id;
// shared.painter.on_window_resize_state_change(id, true);
// }
// shared.painter.on_window_resized(id, width, height);
// repaint_asap = true;
// }
// }
winit::event::WindowEvent::CloseRequested => {
if viewport_id == Some(ViewportId::ROOT) && integration.should_close() {
@@ -899,7 +903,7 @@ impl Viewport {
/// Create winit window, if needed.
fn initialize_window(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
egui_ctx: &egui::Context,
windows_id: &mut HashMap<WindowId, ViewportId>,
painter: &mut egui_wgpu::winit::Painter,
@@ -916,7 +920,7 @@ impl Viewport {
Ok(window) => {
windows_id.insert(window.id(), viewport_id);
let window = Arc::new(window);
let window: Arc<dyn Window> = Arc::from(window);
if let Err(err) =
pollster::block_on(painter.set_window(viewport_id, Some(window.clone())))
@@ -927,13 +931,13 @@ impl Viewport {
self.egui_winit = Some(egui_winit::State::new(
egui_ctx.clone(),
viewport_id,
event_loop,
&event_loop,
Some(window.scale_factor() as f32),
event_loop.system_theme(),
painter.max_texture_side(),
));
egui_winit::update_viewport_info(&mut self.info, egui_ctx, &window, true);
egui_winit::update_viewport_info(&mut self.info, egui_ctx, &*window, true);
self.window = Some(window);
}
Err(err) => {
@@ -945,10 +949,10 @@ impl Viewport {
fn create_window(
egui_ctx: &egui::Context,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
storage: Option<&dyn Storage>,
native_options: &mut NativeOptions,
) -> Result<(Window, ViewportBuilder), winit::error::OsError> {
) -> Result<(Box<dyn Window>, ViewportBuilder), winit::error::RequestError> {
profiling::function_scope!();
let window_settings = epi_integration::load_window_settings(storage);
@@ -961,7 +965,7 @@ fn create_window(
.with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631)
let window = egui_winit::create_window(egui_ctx, event_loop, &viewport_builder)?;
epi_integration::apply_window_settings(&window, window_settings);
epi_integration::apply_window_settings(&*window, window_settings);
Ok((window, viewport_builder))
}
@@ -1004,9 +1008,9 @@ fn render_immediate_viewport(
let (Some(window), Some(egui_winit)) = (&viewport.window, &mut viewport.egui_winit) else {
return;
};
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window, false);
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, &**window, false);
let mut input = egui_winit.take_egui_input(window);
let mut input = egui_winit.take_egui_input(&**window);
input.viewports = viewports
.iter()
.map(|(id, viewport)| (*id, viewport.info.clone()))
@@ -1069,7 +1073,7 @@ fn render_immediate_viewport(
vec![],
);
egui_winit.handle_platform_output(window, platform_output);
egui_winit.handle_platform_output(&**window, platform_output);
handle_viewport_output(
&egui_ctx,
@@ -1120,7 +1124,7 @@ fn handle_viewport_output(
initialize_or_update_viewport(viewports, ids, class, builder, viewport_ui_cb, painter);
if let Some(window) = viewport.window.as_ref() {
let old_inner_size = window.inner_size();
let old_inner_size = window.surface_size();
viewport.deferred_commands.append(&mut commands);
@@ -1128,13 +1132,13 @@ fn handle_viewport_output(
egui_ctx,
&mut viewport.info,
std::mem::take(&mut viewport.deferred_commands),
window,
&**window,
&mut viewport.actions_requested,
);
// For Wayland : https://github.com/emilk/egui/issues/4196
if cfg!(target_os = "linux") {
let new_inner_size = window.inner_size();
let new_inner_size = window.surface_size();
if new_inner_size != old_inner_size
&& let (Some(width), Some(height)) = (
NonZeroU32::new(new_inner_size.width),

View File

@@ -66,7 +66,7 @@ impl From<accesskit_winit::Event> for UserEvent {
pub trait WinitApp {
fn egui_ctx(&self) -> Option<&egui::Context>;
fn window(&self, window_id: WindowId) -> Option<Arc<Window>>;
fn window(&self, window_id: WindowId) -> Option<Arc<dyn Window>>;
fn window_id_from_viewport_id(&self, id: ViewportId) -> Option<WindowId>;
@@ -76,24 +76,24 @@ pub trait WinitApp {
fn run_ui_and_paint(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
) -> crate::Result<EventResult>;
fn suspended(&mut self, event_loop: &ActiveEventLoop) -> crate::Result<EventResult>;
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) -> crate::Result<EventResult>;
fn resumed(&mut self, event_loop: &ActiveEventLoop) -> crate::Result<EventResult>;
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) -> crate::Result<EventResult>;
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
device_id: winit::event::DeviceId,
event_loop: &dyn ActiveEventLoop,
device_id: Option<winit::event::DeviceId>,
event: winit::event::DeviceEvent,
) -> crate::Result<EventResult>;
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) -> crate::Result<EventResult>;