Skip to content

Commit

Permalink
Fix ViewportCommand::InnerSize not resizing viewport on Wayland (em…
Browse files Browse the repository at this point in the history
  • Loading branch information
rustbasic authored and hacknus committed Oct 30, 2024
1 parent b95e317 commit e53e52e
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 160 deletions.
93 changes: 50 additions & 43 deletions crates/eframe/src/native/glow_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ use winit::{

use egui::{
epaint::ahash::HashMap, DeferredViewportUiCallback, ImmediateViewport, ViewportBuilder,
ViewportClass, ViewportId, ViewportIdMap, ViewportIdPair, ViewportIdSet, ViewportInfo,
ViewportOutput,
ViewportClass, ViewportId, ViewportIdMap, ViewportIdPair, ViewportInfo, ViewportOutput,
};
#[cfg(feature = "accesskit")]
use egui_winit::accesskit_winit;
Expand Down Expand Up @@ -103,6 +102,7 @@ struct Viewport {
ids: ViewportIdPair,
class: ViewportClass,
builder: ViewportBuilder,
deferred_commands: Vec<egui::viewport::ViewportCommand>,
info: ViewportInfo,
screenshot_requested: bool,

Expand Down Expand Up @@ -554,7 +554,7 @@ impl GlowWinitRunning {
let Some(window) = viewport.window.as_ref() else {
return EventResult::Wait;
};
egui_winit::update_viewport_info(&mut viewport.info, &egui_ctx, window);
egui_winit::update_viewport_info(&mut viewport.info, &egui_ctx, window, false);

let Some(egui_winit) = viewport.egui_winit.as_mut() else {
return EventResult::Wait;
Expand Down Expand Up @@ -640,6 +640,8 @@ impl GlowWinitRunning {
viewport_output,
} = full_output;

glutin.remove_viewports_not_in(&viewport_output);

let GlutinWindowContext {
viewports,
current_gl_context,
Expand All @@ -649,6 +651,7 @@ impl GlowWinitRunning {
let Some(viewport) = viewports.get_mut(&viewport_id) else {
return EventResult::Wait;
};

viewport.info.events.clear(); // they should have been processed
let window = viewport.window.clone().unwrap();
let gl_surface = viewport.gl_surface.as_ref().unwrap();
Expand Down Expand Up @@ -715,7 +718,7 @@ impl GlowWinitRunning {
}
}

glutin.handle_viewport_output(event_loop, &integration.egui_ctx, viewport_output);
glutin.handle_viewport_output(event_loop, &integration.egui_ctx, &viewport_output);

integration.report_frame_time(frame_timer.total_time_sec()); // don't count auto-save time as part of regular frame time

Expand Down Expand Up @@ -998,8 +1001,7 @@ impl GlutinWindowContext {
if let Some(window) = &window {
viewport_from_window.insert(window.id(), ViewportId::ROOT);
window_from_viewport.insert(ViewportId::ROOT, window.id());
info.minimized = window.is_minimized();
info.maximized = Some(window.is_maximized());
egui_winit::update_viewport_info(&mut info, egui_ctx, window, true);
}

let mut viewports = ViewportIdMap::default();
Expand All @@ -1009,6 +1011,7 @@ impl GlutinWindowContext {
ids: ViewportIdPair::ROOT,
class: ViewportClass::Root,
builder: viewport_builder,
deferred_commands: vec![],
info,
screenshot_requested: false,
viewport_ui_cb: None,
Expand Down Expand Up @@ -1090,8 +1093,8 @@ impl GlutinWindowContext {
&window,
&viewport.builder,
);
viewport.info.minimized = window.is_minimized();
viewport.info.maximized = Some(window.is_maximized());

egui_winit::update_viewport_info(&mut viewport.info, &self.egui_ctx, &window, true);
viewport.window.insert(Arc::new(window))
};

Expand Down Expand Up @@ -1212,75 +1215,88 @@ impl GlutinWindowContext {
self.gl_config.display().get_proc_address(addr)
}

pub(crate) fn remove_viewports_not_in(
&mut self,
viewport_output: &ViewportIdMap<ViewportOutput>,
) {
// GC old viewports
self.viewports
.retain(|id, _| viewport_output.contains_key(id));
self.viewport_from_window
.retain(|_, id| viewport_output.contains_key(id));
self.window_from_viewport
.retain(|id, _| viewport_output.contains_key(id));
}

fn handle_viewport_output(
&mut self,
event_loop: &EventLoopWindowTarget<UserEvent>,
egui_ctx: &egui::Context,
viewport_output: ViewportIdMap<ViewportOutput>,
viewport_output: &ViewportIdMap<ViewportOutput>,
) {
crate::profile_function!();

let active_viewports_ids: ViewportIdSet = viewport_output.keys().copied().collect();

for (
viewport_id,
ViewportOutput {
parent,
class,
builder,
viewport_ui_cb,
commands,
mut commands,
repaint_delay: _, // ignored - we listened to the repaint callback instead
},
) in viewport_output
) in viewport_output.clone()
{
let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent);

let viewport = initialize_or_update_viewport(
egui_ctx,
&mut self.viewports,
ids,
class,
builder,
viewport_ui_cb,
self.focused_viewport,
);

if let Some(window) = &viewport.window {
let old_inner_size = window.inner_size();

let is_viewport_focused = self.focused_viewport == Some(viewport_id);
viewport.deferred_commands.append(&mut commands);

egui_winit::process_viewport_commands(
egui_ctx,
&mut viewport.info,
commands,
std::mem::take(&mut viewport.deferred_commands),
window,
is_viewport_focused,
&mut viewport.screenshot_requested,
);

// For Wayland : https://github.com/emilk/egui/issues/4196
if cfg!(target_os = "linux") {
let new_inner_size = window.inner_size();
if new_inner_size != old_inner_size {
self.resize(viewport_id, new_inner_size);
}
}
}
}

// Create windows for any new viewports:
self.initialize_all_windows(event_loop);

// GC old viewports
self.viewports
.retain(|id, _| active_viewports_ids.contains(id));
self.viewport_from_window
.retain(|_, id| active_viewports_ids.contains(id));
self.window_from_viewport
.retain(|id, _| active_viewports_ids.contains(id));
self.remove_viewports_not_in(viewport_output);
}
}

fn initialize_or_update_viewport<'vp>(
egu_ctx: &egui::Context,
viewports: &'vp mut ViewportIdMap<Viewport>,
fn initialize_or_update_viewport(
viewports: &mut ViewportIdMap<Viewport>,
ids: ViewportIdPair,
class: ViewportClass,
mut builder: ViewportBuilder,
viewport_ui_cb: Option<Arc<dyn Fn(&egui::Context) + Send + Sync>>,
focused_viewport: Option<ViewportId>,
) -> &'vp mut Viewport {
) -> &mut Viewport {
crate::profile_function!();

if builder.icon.is_none() {
Expand All @@ -1298,6 +1314,7 @@ fn initialize_or_update_viewport<'vp>(
ids,
class,
builder,
deferred_commands: vec![],
info: Default::default(),
screenshot_requested: false,
viewport_ui_cb,
Expand All @@ -1315,7 +1332,7 @@ fn initialize_or_update_viewport<'vp>(
viewport.class = class;
viewport.viewport_ui_cb = viewport_ui_cb;

let (delta_commands, recreate) = viewport.builder.patch(builder);
let (mut delta_commands, recreate) = viewport.builder.patch(builder);

if recreate {
log::debug!(
Expand All @@ -1325,18 +1342,10 @@ fn initialize_or_update_viewport<'vp>(
);
viewport.window = None;
viewport.egui_winit = None;
} else if let Some(window) = &viewport.window {
let is_viewport_focused = focused_viewport == Some(ids.this);
egui_winit::process_viewport_commands(
egu_ctx,
&mut viewport.info,
delta_commands,
window,
is_viewport_focused,
&mut viewport.screenshot_requested,
);
}

viewport.deferred_commands.append(&mut delta_commands);

entry.into_mut()
}
}
Expand Down Expand Up @@ -1366,13 +1375,11 @@ fn render_immediate_viewport(
let mut glutin = glutin.borrow_mut();

initialize_or_update_viewport(
egui_ctx,
&mut glutin.viewports,
ids,
ViewportClass::Immediate,
builder,
None,
None,
);

if let Err(err) = glutin.initialize_window(viewport_id, event_loop) {
Expand All @@ -1392,7 +1399,7 @@ fn render_immediate_viewport(
let (Some(egui_winit), Some(window)) = (&mut viewport.egui_winit, &viewport.window) else {
return;
};
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window);
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window, false);

let mut raw_input = egui_winit.take_egui_input(window);
raw_input.viewports = glutin
Expand Down Expand Up @@ -1480,7 +1487,7 @@ fn render_immediate_viewport(

egui_winit.handle_platform_output(window, platform_output);

glutin.handle_viewport_output(event_loop, egui_ctx, viewport_output);
glutin.handle_viewport_output(event_loop, egui_ctx, &viewport_output);
}

#[cfg(feature = "__screenshot")]
Expand Down
Loading

0 comments on commit e53e52e

Please sign in to comment.