Skip to content

Commit

Permalink
Improve multi-viewports across monitors with different scales (#3663)
Browse files Browse the repository at this point in the history
It required some ugly code in `egui-winit` in order to fix this without
breaking sem-ver (I want this to land in a 0.24.1 patch release). I'll
clean up in time for 0.25.

There is still a font rendering bug when using immediate viewports
across multiple viewports, but that's harder to fix.
  • Loading branch information
emilk authored Nov 30, 2023
1 parent 37244e3 commit 61a7b90
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 116 deletions.
4 changes: 3 additions & 1 deletion crates/eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,9 @@ impl EpiIntegration {

pub fn on_window_event(
&mut self,
event: &winit::event::WindowEvent<'_>,
window: &winit::window::Window,
egui_winit: &mut egui_winit::State,
event: &winit::event::WindowEvent<'_>,
) -> EventResponse {
crate::profile_function!(egui_winit::short_window_event_description(event));

Expand All @@ -254,6 +255,7 @@ impl EpiIntegration {
_ => {}
}

egui_winit.update_pixels_per_point(&self.egui_ctx, window);
egui_winit.on_window_event(&self.egui_ctx, event)
}

Expand Down
60 changes: 27 additions & 33 deletions crates/eframe/src/native/glow_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ use egui::{
};
#[cfg(feature = "accesskit")]
use egui_winit::accesskit_winit;
use egui_winit::{
apply_viewport_builder_to_new_window, create_winit_window_builder, process_viewport_commands,
EventResponse,
};

use crate::{
native::{epi_integration::EpiIntegration, winit_integration::create_egui_context},
Expand Down Expand Up @@ -513,11 +509,13 @@ impl GlowWinitRunning {

let (raw_input, viewport_ui_cb) = {
let mut glutin = self.glutin.borrow_mut();
let egui_ctx = glutin.egui_ctx.clone();
let viewport = glutin.viewports.get_mut(&viewport_id).unwrap();
viewport.update_viewport_info();
let window = viewport.window.as_ref().unwrap();
egui_winit::update_viewport_info(&mut viewport.info, &egui_ctx, window);

let egui_winit = viewport.egui_winit.as_mut().unwrap();
egui_winit.update_pixels_per_point(&egui_ctx, window);
let mut raw_input = egui_winit.take_egui_input(window);
let viewport_ui_cb = viewport.viewport_ui_cb.clone();

Expand Down Expand Up @@ -744,15 +742,17 @@ impl GlowWinitRunning {
return EventResult::Exit;
}

let mut event_response = EventResponse {
let mut event_response = egui_winit::EventResponse {
consumed: false,
repaint: false,
};
if let Some(viewport_id) = viewport_id {
if let Some(viewport) = glutin.viewports.get_mut(&viewport_id) {
event_response = self
.integration
.on_window_event(event, viewport.egui_winit.as_mut().unwrap());
if let (Some(window), Some(egui_winit)) =
(&viewport.window, &mut viewport.egui_winit)
{
event_response = self.integration.on_window_event(window, egui_winit, event);
}
}
}

Expand Down Expand Up @@ -823,7 +823,7 @@ impl GlutinWindowContext {
let display_builder = glutin_winit::DisplayBuilder::new()
// we might want to expose this option to users in the future. maybe using an env var or using native_options.
.with_preference(glutin_winit::ApiPrefence::FallbackEgl) // https://github.com/emilk/egui/issues/2520#issuecomment-1367841150
.with_window_builder(Some(create_winit_window_builder(
.with_window_builder(Some(egui_winit::create_winit_window_builder(
egui_ctx,
event_loop,
viewport_builder.clone(),
Expand All @@ -849,7 +849,7 @@ impl GlutinWindowContext {
.map_err(|e| crate::Error::NoGlutinConfigs(config_template_builder.build(), e))?
};
if let Some(window) = &window {
apply_viewport_builder_to_new_window(window, &viewport_builder);
egui_winit::apply_viewport_builder_to_window(egui_ctx, window, &viewport_builder);
}

let gl_display = gl_config.display();
Expand Down Expand Up @@ -981,12 +981,18 @@ impl GlutinWindowContext {
window
} else {
log::trace!("Window doesn't exist yet. Creating one now with finalize_window");
let window = glutin_winit::finalize_window(
let window_builder = egui_winit::create_winit_window_builder(
&self.egui_ctx,
event_loop,
create_winit_window_builder(&self.egui_ctx, event_loop, viewport.builder.clone()),
&self.gl_config,
)?;
apply_viewport_builder_to_new_window(&window, &viewport.builder);
viewport.builder.clone(),
);
let window =
glutin_winit::finalize_window(event_loop, window_builder, &self.gl_config)?;
egui_winit::apply_viewport_builder_to_window(
&self.egui_ctx,
&window,
&viewport.builder,
);
viewport.info.minimized = window.is_minimized();
viewport.info.maximized = Some(window.is_maximized());
viewport.window.insert(Rc::new(window))
Expand Down Expand Up @@ -1167,19 +1173,6 @@ impl GlutinWindowContext {
}
}

impl Viewport {
/// Update the stored `ViewportInfo`.
fn update_viewport_info(&mut self) {
let Some(window) = &self.window else {
return;
};
let Some(egui_winit) = &self.egui_winit else {
return;
};
egui_winit.update_viewport_info(&mut self.info, window);
}
}

fn initialize_or_update_viewport<'vp>(
egu_ctx: &'_ egui::Context,
viewports: &'vp mut ViewportIdMap<Viewport>,
Expand Down Expand Up @@ -1235,7 +1228,7 @@ fn initialize_or_update_viewport<'vp>(
viewport.egui_winit = None;
} else if let Some(window) = &viewport.window {
let is_viewport_focused = focused_viewport == Some(ids.this);
process_viewport_commands(
egui_winit::process_viewport_commands(
egu_ctx,
&mut viewport.info,
delta_commands,
Expand Down Expand Up @@ -1294,15 +1287,16 @@ fn render_immediate_viewport(
let Some(viewport) = glutin.viewports.get_mut(&ids.this) else {
return;
};
viewport.update_viewport_info();
let Some(winit_state) = &mut viewport.egui_winit else {
let Some(egui_winit) = &mut viewport.egui_winit else {
return;
};
let Some(window) = &viewport.window else {
return;
};
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window);

let mut raw_input = winit_state.take_egui_input(window);
egui_winit.update_pixels_per_point(egui_ctx, window);
let mut raw_input = egui_winit.take_egui_input(window);
raw_input.viewports = glutin
.viewports
.iter()
Expand Down
54 changes: 19 additions & 35 deletions crates/eframe/src/native/wgpu_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ use egui::{
};
#[cfg(feature = "accesskit")]
use egui_winit::accesskit_winit;
use egui_winit::{
apply_viewport_builder_to_new_window, create_winit_window_builder, process_viewport_commands,
};

use crate::{
native::{epi_integration::EpiIntegration, winit_integration::EventResult},
Expand Down Expand Up @@ -485,7 +482,10 @@ impl WgpuWinitRunning {
let mut shared_lock = shared.borrow_mut();

let SharedState {
viewports, painter, ..
egui_ctx,
viewports,
painter,
..
} = &mut *shared_lock;

if viewport_id != ViewportId::ROOT {
Expand All @@ -508,12 +508,12 @@ impl WgpuWinitRunning {
let Some(viewport) = viewports.get_mut(&viewport_id) else {
return EventResult::Wait;
};
viewport.update_viewport_info();

let Viewport {
viewport_ui_cb,
window,
egui_winit,
info,
..
} = viewport;

Expand All @@ -522,6 +522,7 @@ impl WgpuWinitRunning {
let Some(window) = window else {
return EventResult::Wait;
};
egui_winit::update_viewport_info(info, &integration.egui_ctx, window);

{
crate::profile_scope!("set_window");
Expand All @@ -531,7 +532,9 @@ impl WgpuWinitRunning {
}
}

let mut raw_input = egui_winit.as_mut().unwrap().take_egui_input(window);
let egui_winit = egui_winit.as_mut().unwrap();
egui_winit.update_pixels_per_point(egui_ctx, window);
let mut raw_input = egui_winit.take_egui_input(window);

integration.pre_update();

Expand Down Expand Up @@ -745,10 +748,11 @@ impl WgpuWinitRunning {
let event_response = viewport_id
.and_then(|viewport_id| {
shared.viewports.get_mut(&viewport_id).and_then(|viewport| {
viewport
.egui_winit
.as_mut()
.map(|egui_winit| integration.on_window_event(event, egui_winit))
Some(integration.on_window_event(
viewport.window.as_deref()?,
viewport.egui_winit.as_mut()?,
event,
))
})
})
.unwrap_or_default();
Expand Down Expand Up @@ -779,12 +783,8 @@ impl Viewport {

let viewport_id = self.ids.this;

match create_winit_window_builder(egui_ctx, event_loop, self.builder.clone())
.build(event_loop)
{
match egui_winit::create_window(egui_ctx, event_loop, &self.builder) {
Ok(window) => {
apply_viewport_builder_to_new_window(&window, &self.builder);

windows_id.insert(window.id(), viewport_id);

if let Err(err) = pollster::block_on(painter.set_window(viewport_id, Some(&window)))
Expand All @@ -809,18 +809,6 @@ impl Viewport {
}
}
}

/// Update the stored `ViewportInfo`.
pub fn update_viewport_info(&mut self) {
crate::profile_function!();
let Some(window) = &self.window else {
return;
};
let Some(egui_winit) = &self.egui_winit else {
return;
};
egui_winit.update_viewport_info(&mut self.info, window);
}
}

fn create_window(
Expand All @@ -840,12 +828,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 = {
crate::profile_scope!("WindowBuilder::build");
create_winit_window_builder(egui_ctx, event_loop, viewport_builder.clone())
.build(event_loop)?
};
apply_viewport_builder_to_new_window(&window, &viewport_builder);
let window = egui_winit::create_window(egui_ctx, event_loop, &viewport_builder)?;
epi_integration::apply_window_settings(&window, window_settings);
Ok((window, viewport_builder))
}
Expand Down Expand Up @@ -885,12 +868,13 @@ fn render_immediate_viewport(
if viewport.window.is_none() {
viewport.init_window(egui_ctx, viewport_from_window, painter, event_loop);
}
viewport.update_viewport_info();

let (Some(window), Some(winit_state)) = (&viewport.window, &mut viewport.egui_winit) else {
return;
};
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window);

winit_state.update_pixels_per_point(egui_ctx, window);
let mut input = winit_state.take_egui_input(window);
input.viewports = viewports
.iter()
Expand Down Expand Up @@ -1056,7 +1040,7 @@ fn initialize_or_update_viewport<'vp>(
viewport.egui_winit = None;
} else if let Some(window) = &viewport.window {
let is_viewport_focused = focused_viewport == Some(ids.this);
process_viewport_commands(
egui_winit::process_viewport_commands(
egui_ctx,
&mut viewport.info,
delta_commands,
Expand Down
Loading

0 comments on commit 61a7b90

Please sign in to comment.