mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 05:40:03 -04:00
Introduce global zoom_factor (#3608)
* Closes https://github.com/emilk/egui/issues/3602 You can now zoom any egui app by pressing Cmd+Plus, Cmd+Minus or Cmd+0, just like in a browser. This will change the current `zoom_factor` (default 1.0) which is persisted in the egui memory, and is the same for all viewports. You can turn off the keyboard shortcuts with `ctx.options_mut(|o| o.zoom_with_keyboard = false);` `zoom_factor` can also be explicitly read/written with `ctx.zoom_factor()` and `ctx.set_zoom_factor()`. This redefines `pixels_per_point` as `zoom_factor * native_pixels_per_point`, where `native_pixels_per_point` is whatever is the native scale factor for the monitor that the current viewport is in. This adds some complexity to the interaction with winit, since we need to know the current `zoom_factor` in a lot of places, because all egui IO is done in ui points. I'm pretty sure this PR fixes a bunch of subtle bugs though that used to be in this code. `egui::gui_zoom::zoom_with_keyboard_shortcuts` is now gone, and is no longer needed, as this is now the default behavior. `Context::set_pixels_per_point` is still there, but it is recommended you use `Context::set_zoom_factor` instead.
This commit is contained in:
@@ -24,8 +24,8 @@ use egui_winit::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
native::epi_integration::EpiIntegration, App, AppCreator, CreationContext, NativeOptions,
|
||||
Result, Storage,
|
||||
native::{epi_integration::EpiIntegration, winit_integration::create_egui_context},
|
||||
App, AppCreator, CreationContext, NativeOptions, Result, Storage,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -86,6 +86,8 @@ struct GlowWinitRunning {
|
||||
/// The setup is divided between the `new` fn and `on_resume` fn. we can just assume that `on_resume` is a continuation of
|
||||
/// `new` fn on all platforms. only on android, do we get multiple resumed events because app can be suspended.
|
||||
struct GlutinWindowContext {
|
||||
egui_ctx: egui::Context,
|
||||
|
||||
swap_interval: glutin::surface::SwapInterval,
|
||||
gl_config: glutin::config::Config,
|
||||
|
||||
@@ -138,6 +140,7 @@ impl GlowWinitApp {
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn create_glutin_windowed_context(
|
||||
egui_ctx: &egui::Context,
|
||||
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||
storage: Option<&dyn Storage>,
|
||||
native_options: &mut NativeOptions,
|
||||
@@ -146,11 +149,16 @@ impl GlowWinitApp {
|
||||
|
||||
let window_settings = epi_integration::load_window_settings(storage);
|
||||
|
||||
let winit_window_builder =
|
||||
epi_integration::viewport_builder(event_loop, native_options, window_settings);
|
||||
let winit_window_builder = epi_integration::viewport_builder(
|
||||
egui_ctx.zoom_factor(),
|
||||
event_loop,
|
||||
native_options,
|
||||
window_settings,
|
||||
);
|
||||
|
||||
let mut glutin_window_context =
|
||||
unsafe { GlutinWindowContext::new(winit_window_builder, native_options, event_loop)? };
|
||||
let mut glutin_window_context = unsafe {
|
||||
GlutinWindowContext::new(egui_ctx, winit_window_builder, native_options, event_loop)?
|
||||
};
|
||||
|
||||
// Creates the window - must come before we create our glow context
|
||||
glutin_window_context.on_resume(event_loop)?;
|
||||
@@ -190,7 +198,10 @@ impl GlowWinitApp {
|
||||
.unwrap_or(&self.app_name),
|
||||
);
|
||||
|
||||
let egui_ctx = create_egui_context(storage.as_deref());
|
||||
|
||||
let (mut glutin, painter) = Self::create_glutin_windowed_context(
|
||||
&egui_ctx,
|
||||
event_loop,
|
||||
storage.as_deref(),
|
||||
&mut self.native_options,
|
||||
@@ -209,12 +220,12 @@ impl GlowWinitApp {
|
||||
winit_integration::system_theme(&glutin.window(ViewportId::ROOT), &self.native_options);
|
||||
|
||||
let integration = EpiIntegration::new(
|
||||
egui_ctx,
|
||||
&glutin.window(ViewportId::ROOT),
|
||||
system_theme,
|
||||
&self.app_name,
|
||||
&self.native_options,
|
||||
storage,
|
||||
winit_integration::IS_DESKTOP,
|
||||
Some(gl.clone()),
|
||||
#[cfg(feature = "wgpu")]
|
||||
None,
|
||||
@@ -640,7 +651,7 @@ impl GlowWinitRunning {
|
||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||
}
|
||||
|
||||
glutin.handle_viewport_output(viewport_output);
|
||||
glutin.handle_viewport_output(&integration.egui_ctx, viewport_output);
|
||||
|
||||
if integration.should_close() {
|
||||
EventResult::Exit
|
||||
@@ -761,6 +772,7 @@ impl GlowWinitRunning {
|
||||
impl GlutinWindowContext {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn new(
|
||||
egui_ctx: &egui::Context,
|
||||
viewport_builder: ViewportBuilder,
|
||||
native_options: &NativeOptions,
|
||||
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||
@@ -812,7 +824,11 @@ 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(viewport_builder.clone())));
|
||||
.with_window_builder(Some(create_winit_window_builder(
|
||||
egui_ctx,
|
||||
event_loop,
|
||||
viewport_builder.clone(),
|
||||
)));
|
||||
|
||||
let (window, gl_config) = {
|
||||
crate::profile_scope!("DisplayBuilder::build");
|
||||
@@ -908,6 +924,7 @@ impl GlutinWindowContext {
|
||||
// https://github.com/emilk/egui/pull/2541#issuecomment-1370767582
|
||||
|
||||
let mut slf = GlutinWindowContext {
|
||||
egui_ctx: egui_ctx.clone(),
|
||||
swap_interval,
|
||||
gl_config,
|
||||
current_gl_context: None,
|
||||
@@ -967,7 +984,7 @@ impl GlutinWindowContext {
|
||||
log::trace!("Window doesn't exist yet. Creating one now with finalize_window");
|
||||
let window = glutin_winit::finalize_window(
|
||||
event_loop,
|
||||
create_winit_window_builder(viewport.builder.clone()),
|
||||
create_winit_window_builder(&self.egui_ctx, event_loop, viewport.builder.clone()),
|
||||
&self.gl_config,
|
||||
)?;
|
||||
apply_viewport_builder_to_new_window(&window, &viewport.builder);
|
||||
@@ -1095,7 +1112,11 @@ impl GlutinWindowContext {
|
||||
self.gl_config.display().get_proc_address(addr)
|
||||
}
|
||||
|
||||
fn handle_viewport_output(&mut self, viewport_output: ViewportIdMap<ViewportOutput>) {
|
||||
fn handle_viewport_output(
|
||||
&mut self,
|
||||
egui_ctx: &egui::Context,
|
||||
viewport_output: ViewportIdMap<ViewportOutput>,
|
||||
) {
|
||||
crate::profile_function!();
|
||||
|
||||
let active_viewports_ids: ViewportIdSet = viewport_output.keys().copied().collect();
|
||||
@@ -1115,6 +1136,7 @@ impl GlutinWindowContext {
|
||||
let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent);
|
||||
|
||||
let viewport = initialize_or_update_viewport(
|
||||
egui_ctx,
|
||||
&mut self.viewports,
|
||||
ids,
|
||||
class,
|
||||
@@ -1126,6 +1148,7 @@ impl GlutinWindowContext {
|
||||
if let Some(window) = &viewport.window {
|
||||
let is_viewport_focused = self.focused_viewport == Some(viewport_id);
|
||||
egui_winit::process_viewport_commands(
|
||||
egui_ctx,
|
||||
&mut viewport.info,
|
||||
commands,
|
||||
window,
|
||||
@@ -1158,14 +1181,15 @@ impl Viewport {
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_or_update_viewport(
|
||||
viewports: &mut ViewportIdMap<Viewport>,
|
||||
fn initialize_or_update_viewport<'vp>(
|
||||
egu_ctx: &'_ egui::Context,
|
||||
viewports: &'vp 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>,
|
||||
) -> &mut Viewport {
|
||||
) -> &'vp mut Viewport {
|
||||
crate::profile_function!();
|
||||
|
||||
if builder.icon.is_none() {
|
||||
@@ -1213,6 +1237,7 @@ fn initialize_or_update_viewport(
|
||||
} else if let Some(window) = &viewport.window {
|
||||
let is_viewport_focused = focused_viewport == Some(ids.this);
|
||||
process_viewport_commands(
|
||||
egu_ctx,
|
||||
&mut viewport.info,
|
||||
delta_commands,
|
||||
window,
|
||||
@@ -1248,6 +1273,7 @@ fn render_immediate_viewport(
|
||||
let mut glutin = glutin.borrow_mut();
|
||||
|
||||
let viewport = initialize_or_update_viewport(
|
||||
egui_ctx,
|
||||
&mut glutin.viewports,
|
||||
ids,
|
||||
ViewportClass::Immediate,
|
||||
@@ -1363,7 +1389,7 @@ fn render_immediate_viewport(
|
||||
|
||||
winit_state.handle_platform_output(window, egui_ctx, platform_output);
|
||||
|
||||
glutin.handle_viewport_output(viewport_output);
|
||||
glutin.handle_viewport_output(egui_ctx, viewport_output);
|
||||
}
|
||||
|
||||
#[cfg(feature = "__screenshot")]
|
||||
|
||||
Reference in New Issue
Block a user