Skip to content

Commit 0c528fb

Browse files
authored
Fix crash when changing viewport settings (#4862)
* Fixes #3959 There are two bugs racing each other here, which is why it sometimes crashes and sometimes the app just silently exists Bug 1 When the window is recreated a Destroyed event arrives (due to the Drop of the old window). The code that receives this event does not look to see if its the main viewport or a secondary one and unconditionally closes the app. The code path for other platforms is slightly different and does check. I have moved the code that handles the destroy to be in the same place and have the same behavior as the other platforms. Bug 2 At recreate time the window and winit entries of the viewport are set to None (forcin g them to be recreated). But the surface is still bound to the old window, this causes the next context switch to fail. So I simply added a viewport.gl_surface = None too, This is my first egui PR so I hope I have not broken anything. If nothing else I understand a little better how egui works.
1 parent 5a196f6 commit 0c528fb

3 files changed

Lines changed: 33 additions & 10 deletions

File tree

crates/eframe/src/native/epi_integration.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,6 @@ impl EpiIntegration {
236236
use winit::event::{ElementState, MouseButton, WindowEvent};
237237

238238
match event {
239-
WindowEvent::Destroyed => {
240-
log::debug!("Received WindowEvent::Destroyed");
241-
self.close = true;
242-
}
243239
WindowEvent::MouseInput {
244240
button: MouseButton::Left,
245241
state: ElementState::Pressed,

crates/eframe/src/native/glow_integration.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,18 @@ impl GlowWinitRunning {
803803
}
804804
}
805805

806+
winit::event::WindowEvent::Destroyed => {
807+
log::debug!(
808+
"Received WindowEvent::Destroyed for viewport {:?}",
809+
viewport_id
810+
);
811+
if viewport_id == Some(ViewportId::ROOT) {
812+
return EventResult::Exit;
813+
} else {
814+
return EventResult::Wait;
815+
}
816+
}
817+
806818
_ => {}
807819
}
808820

@@ -1360,6 +1372,7 @@ fn initialize_or_update_viewport(
13601372
);
13611373
viewport.window = None;
13621374
viewport.egui_winit = None;
1375+
viewport.gl_surface = None;
13631376
}
13641377

13651378
viewport.deferred_commands.append(&mut delta_commands);

crates/eframe/src/native/wgpu_integration.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ impl WgpuWinitApp {
158158
ViewportClass::Root,
159159
self.native_options.viewport.clone(),
160160
None,
161+
painter,
161162
)
162163
.initialize_window(event_loop, egui_ctx, viewport_from_window, painter);
163164
}
@@ -927,8 +928,14 @@ fn render_immediate_viewport(
927928
..
928929
} = &mut *shared.borrow_mut();
929930

930-
let viewport =
931-
initialize_or_update_viewport(viewports, ids, ViewportClass::Immediate, builder, None);
931+
let viewport = initialize_or_update_viewport(
932+
viewports,
933+
ids,
934+
ViewportClass::Immediate,
935+
builder,
936+
None,
937+
painter,
938+
);
932939
if viewport.window.is_none() {
933940
event_loop_context::with_current_event_loop(|event_loop| {
934941
viewport.initialize_window(event_loop, egui_ctx, viewport_from_window, painter);
@@ -1051,7 +1058,7 @@ fn handle_viewport_output(
10511058
let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent);
10521059

10531060
let viewport =
1054-
initialize_or_update_viewport(viewports, ids, class, builder, viewport_ui_cb);
1061+
initialize_or_update_viewport(viewports, ids, class, builder, viewport_ui_cb, painter);
10551062

10561063
if let Some(window) = viewport.window.as_ref() {
10571064
let old_inner_size = window.inner_size();
@@ -1084,13 +1091,14 @@ fn handle_viewport_output(
10841091
remove_viewports_not_in(viewports, painter, viewport_from_window, viewport_output);
10851092
}
10861093

1087-
fn initialize_or_update_viewport(
1088-
viewports: &mut Viewports,
1094+
fn initialize_or_update_viewport<'a>(
1095+
viewports: &'a mut Viewports,
10891096
ids: ViewportIdPair,
10901097
class: ViewportClass,
10911098
mut builder: ViewportBuilder,
10921099
viewport_ui_cb: Option<Arc<dyn Fn(&egui::Context) + Send + Sync>>,
1093-
) -> &mut Viewport {
1100+
painter: &mut egui_wgpu::winit::Painter,
1101+
) -> &'a mut Viewport {
10941102
crate::profile_function!();
10951103

10961104
if builder.icon.is_none() {
@@ -1135,6 +1143,12 @@ fn initialize_or_update_viewport(
11351143
);
11361144
viewport.window = None;
11371145
viewport.egui_winit = None;
1146+
if let Err(err) = pollster::block_on(painter.set_window(viewport.ids.this, None)) {
1147+
log::error!(
1148+
"when rendering viewport_id={:?}, set_window Error {err}",
1149+
viewport.ids.this
1150+
);
1151+
}
11381152
}
11391153

11401154
viewport.deferred_commands.append(&mut delta_commands);

0 commit comments

Comments
 (0)