Fix incorrect window sizes for non-resizable windows on Wayland (#7103)
Using physical window sizes leads to all kinds of fun stuff: winit always uses scale factor 1.0 on start to convert it back to logical pixels and uses these logical pixels to set min/max size for non-resizeable windows. You're supposed to adjust size after getting a scale change event if you're using physical sizes, but adjusting min/max sizes doesn't seem to work on sway, so the window is stuck with an incorrect size. The scale factor we guessed might also be wrong even if there's only a single display since it doesn't take fractional scale into account. TL;DR: winit actually wants logical sizes in these methods (since Wayland in general operates mostly on logical sizes) and converting them back and forth is lossy. <!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * The PR title is what ends up in the changelog, so make it descriptive! * If applicable, add a screenshot or gif. * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`, or a new example. * Do NOT open PR:s from your `master` branch, as that makes it hard for maintainers to test and add commits to your PR. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./scripts/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review your PR, but my time is limited! --> * Closes https://github.com/emilk/egui/issues/7095 * [x] I have followed the instructions in the PR template --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
98add13933
commit
853feea464
|
|
@ -959,7 +959,6 @@ impl GlutinWindowContext {
|
||||||
.with_preference(glutin_winit::ApiPreference::FallbackEgl)
|
.with_preference(glutin_winit::ApiPreference::FallbackEgl)
|
||||||
.with_window_attributes(Some(egui_winit::create_winit_window_attributes(
|
.with_window_attributes(Some(egui_winit::create_winit_window_attributes(
|
||||||
egui_ctx,
|
egui_ctx,
|
||||||
event_loop,
|
|
||||||
viewport_builder.clone(),
|
viewport_builder.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
@ -1113,7 +1112,6 @@ impl GlutinWindowContext {
|
||||||
log::debug!("Creating a window for viewport {viewport_id:?}");
|
log::debug!("Creating a window for viewport {viewport_id:?}");
|
||||||
let window_attributes = egui_winit::create_winit_window_attributes(
|
let window_attributes = egui_winit::create_winit_window_attributes(
|
||||||
&self.egui_ctx,
|
&self.egui_ctx,
|
||||||
event_loop,
|
|
||||||
viewport.builder.clone(),
|
viewport.builder.clone(),
|
||||||
);
|
);
|
||||||
if window_attributes.transparent()
|
if window_attributes.transparent()
|
||||||
|
|
|
||||||
|
|
@ -1566,8 +1566,7 @@ pub fn create_window(
|
||||||
) -> Result<Window, winit::error::OsError> {
|
) -> Result<Window, winit::error::OsError> {
|
||||||
profiling::function_scope!();
|
profiling::function_scope!();
|
||||||
|
|
||||||
let window_attributes =
|
let window_attributes = create_winit_window_attributes(egui_ctx, viewport_builder.clone());
|
||||||
create_winit_window_attributes(egui_ctx, event_loop, viewport_builder.clone());
|
|
||||||
let window = event_loop.create_window(window_attributes)?;
|
let window = event_loop.create_window(window_attributes)?;
|
||||||
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
|
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
|
||||||
Ok(window)
|
Ok(window)
|
||||||
|
|
@ -1575,28 +1574,10 @@ pub fn create_window(
|
||||||
|
|
||||||
pub fn create_winit_window_attributes(
|
pub fn create_winit_window_attributes(
|
||||||
egui_ctx: &egui::Context,
|
egui_ctx: &egui::Context,
|
||||||
event_loop: &ActiveEventLoop,
|
|
||||||
viewport_builder: ViewportBuilder,
|
viewport_builder: ViewportBuilder,
|
||||||
) -> winit::window::WindowAttributes {
|
) -> winit::window::WindowAttributes {
|
||||||
profiling::function_scope!();
|
profiling::function_scope!();
|
||||||
|
|
||||||
// We set sizes and positions in egui:s own ui points, which depends on the egui
|
|
||||||
// zoom_factor and the native pixels per point, so we need to know that here.
|
|
||||||
// We don't know what monitor the window will appear on though, but
|
|
||||||
// we'll try to fix that after the window is created in the call to `apply_viewport_builder_to_window`.
|
|
||||||
let native_pixels_per_point = event_loop
|
|
||||||
.primary_monitor()
|
|
||||||
.or_else(|| event_loop.available_monitors().next())
|
|
||||||
.map_or_else(
|
|
||||||
|| {
|
|
||||||
log::debug!("Failed to find a monitor - assuming native_pixels_per_point of 1.0");
|
|
||||||
1.0
|
|
||||||
},
|
|
||||||
|m| m.scale_factor() as f32,
|
|
||||||
);
|
|
||||||
let zoom_factor = egui_ctx.zoom_factor();
|
|
||||||
let pixels_per_point = zoom_factor * native_pixels_per_point;
|
|
||||||
|
|
||||||
let ViewportBuilder {
|
let ViewportBuilder {
|
||||||
title,
|
title,
|
||||||
position,
|
position,
|
||||||
|
|
@ -1672,40 +1653,46 @@ pub fn create_winit_window_attributes(
|
||||||
})
|
})
|
||||||
.with_active(active.unwrap_or(true));
|
.with_active(active.unwrap_or(true));
|
||||||
|
|
||||||
|
// Here and below: we create `LogicalSize` / `LogicalPosition` taking
|
||||||
|
// zoom factor into account. We don't have a good way to get physical size here,
|
||||||
|
// and trying to do it anyway leads to weird bugs on Wayland, see:
|
||||||
|
// https://github.com/emilk/egui/issues/7095#issuecomment-2920545377
|
||||||
|
// https://github.com/rust-windowing/winit/issues/4266
|
||||||
|
#[expect(
|
||||||
|
clippy::disallowed_types,
|
||||||
|
reason = "zoom factor is manually accounted for"
|
||||||
|
)]
|
||||||
#[cfg(not(target_os = "ios"))]
|
#[cfg(not(target_os = "ios"))]
|
||||||
if let Some(size) = inner_size {
|
{
|
||||||
window_attributes = window_attributes.with_inner_size(PhysicalSize::new(
|
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||||
pixels_per_point * size.x,
|
let zoom_factor = egui_ctx.zoom_factor();
|
||||||
pixels_per_point * size.y,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "ios"))]
|
if let Some(size) = inner_size {
|
||||||
if let Some(size) = min_inner_size {
|
window_attributes = window_attributes
|
||||||
window_attributes = window_attributes.with_min_inner_size(PhysicalSize::new(
|
.with_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
|
||||||
pixels_per_point * size.x,
|
}
|
||||||
pixels_per_point * size.y,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "ios"))]
|
if let Some(size) = min_inner_size {
|
||||||
if let Some(size) = max_inner_size {
|
window_attributes = window_attributes
|
||||||
window_attributes = window_attributes.with_max_inner_size(PhysicalSize::new(
|
.with_min_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
|
||||||
pixels_per_point * size.x,
|
}
|
||||||
pixels_per_point * size.y,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "ios"))]
|
if let Some(size) = max_inner_size {
|
||||||
if let Some(pos) = position {
|
window_attributes = window_attributes
|
||||||
window_attributes = window_attributes.with_position(PhysicalPosition::new(
|
.with_max_inner_size(LogicalSize::new(zoom_factor * size.x, zoom_factor * size.y));
|
||||||
pixels_per_point * pos.x,
|
}
|
||||||
pixels_per_point * pos.y,
|
|
||||||
));
|
if let Some(pos) = position {
|
||||||
|
window_attributes = window_attributes.with_position(LogicalPosition::new(
|
||||||
|
zoom_factor * pos.x,
|
||||||
|
zoom_factor * pos.y,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
{
|
{
|
||||||
// Unused:
|
// Unused:
|
||||||
|
_ = egui_ctx;
|
||||||
_ = pixels_per_point;
|
_ = pixels_per_point;
|
||||||
_ = position;
|
_ = position;
|
||||||
_ = inner_size;
|
_ = inner_size;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue