On X11, make WINIT_HIDPI_FACTOR dominate Xft.dpi in some cases (#1354)

* On X11, make `WINIT_HIDPI_FACTOR` dominate `Xft.dpi` in some cases

This commit makes `WINIT_HIDPI_FACTOR` dominate `Xft.dpi` in general and
adds a special value `0` for `WINIT_HIDPI_FACTOR` to use winit computed
DPI factor with randr over Xft.dpi.

* Use `randr` instead of `0` for auto dpi scaling

* Update CHANGELOG

* blow up on wrong env var

* Allow empty string for env var
This commit is contained in:
Kirill Chibisov 2020-01-04 02:15:47 +03:00 committed by Osspial
parent 7367b8be6c
commit 114c18e70d
2 changed files with 53 additions and 19 deletions

View file

@ -23,6 +23,8 @@
- On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior. - On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior.
- Add `DeviceEvent::ModifiersChanged`. - Add `DeviceEvent::ModifiersChanged`.
- Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`. - Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`.
- On X11, `WINIT_HIDPI_FACTOR` now dominates `Xft.dpi` when picking DPI factor for output.
- On X11, add special value `randr` for `WINIT_HIDPI_FACTOR` to make winit use self computed DPI factor instead of the one from `Xft.dpi`.
# 0.20.0 Alpha 5 (2019-12-09) # 0.20.0 Alpha 5 (2019-12-09)

View file

@ -6,24 +6,17 @@ use super::{
}; };
use crate::{dpi::validate_hidpi_factor, platform_impl::platform::x11::VideoMode}; use crate::{dpi::validate_hidpi_factor, platform_impl::platform::x11::VideoMode};
/// Represents values of `WINIT_HIDPI_FACTOR`.
pub enum EnvVarDPI {
Randr,
Scale(f64),
NotSet,
}
pub fn calc_dpi_factor( pub fn calc_dpi_factor(
(width_px, height_px): (u32, u32), (width_px, height_px): (u32, u32),
(width_mm, height_mm): (u64, u64), (width_mm, height_mm): (u64, u64),
) -> f64 { ) -> f64 {
// Override DPI if `WINIT_HIDPI_FACTOR` variable is set
let dpi_override = env::var("WINIT_HIDPI_FACTOR")
.ok()
.and_then(|var| f64::from_str(&var).ok());
if let Some(dpi_override) = dpi_override {
if !validate_hidpi_factor(dpi_override) {
panic!(
"`WINIT_HIDPI_FACTOR` invalid; DPI factors must be normal floats greater than 0. Got `{}`",
dpi_override,
);
}
return dpi_override;
}
// See http://xpra.org/trac/ticket/728 for more information. // See http://xpra.org/trac/ticket/728 for more information.
if width_mm == 0 || height_mm == 0 { if width_mm == 0 || height_mm == 0 {
warn!("XRandR reported that the display's 0mm in size, which is certifiably insane"); warn!("XRandR reported that the display's 0mm in size, which is certifiably insane");
@ -107,16 +100,55 @@ impl XConnection {
(*output_info).nameLen as usize, (*output_info).nameLen as usize,
); );
let name = String::from_utf8_lossy(name_slice).into(); let name = String::from_utf8_lossy(name_slice).into();
let hidpi_factor = if let Some(dpi) = self.get_xft_dpi() { // Override DPI if `WINIT_HIDPI_FACTOR` variable is set
dpi / 96. let dpi_env = env::var("WINIT_HIDPI_FACTOR").ok().map_or_else(
} else { || EnvVarDPI::NotSet,
calc_dpi_factor( |var| {
if var.to_lowercase() == "randr" {
EnvVarDPI::Randr
} else if let Ok(dpi) = f64::from_str(&var) {
EnvVarDPI::Scale(dpi)
} else if var.is_empty() {
EnvVarDPI::NotSet
} else {
panic!(
"`WINIT_HIDPI_FACTOR` invalid; DPI factors must be either normal floats greater than 0, or `randr`. Got `{}`",
var
);
}
},
);
let hidpi_factor = match dpi_env {
EnvVarDPI::Randr => calc_dpi_factor(
((*crtc).width as u32, (*crtc).height as u32), ((*crtc).width as u32, (*crtc).height as u32),
( (
(*output_info).mm_width as u64, (*output_info).mm_width as u64,
(*output_info).mm_height as u64, (*output_info).mm_height as u64,
), ),
) ),
EnvVarDPI::Scale(dpi_override) => {
if !validate_hidpi_factor(dpi_override) {
panic!(
"`WINIT_HIDPI_FACTOR` invalid; DPI factors must be either normal floats greater than 0, or `randr`. Got `{}`",
dpi_override,
);
}
dpi_override
}
EnvVarDPI::NotSet => {
if let Some(dpi) = self.get_xft_dpi() {
dpi / 96.
} else {
calc_dpi_factor(
((*crtc).width as u32, (*crtc).height as u32),
(
(*output_info).mm_width as u64,
(*output_info).mm_height as u64,
),
)
}
}
}; };
(self.xrandr.XRRFreeOutputInfo)(output_info); (self.xrandr.XRRFreeOutputInfo)(output_info);