diff --git a/src/state.rs b/src/state.rs index 063cf051..80bdb2ec 100644 --- a/src/state.rs +++ b/src/state.rs @@ -385,19 +385,20 @@ Outcome: let ideal_height = IDEAL_TARGET_SIZE * ROW_COUNT as i32; let ideal_height_px = (ideal_height * density).ceil().0 as u32; + let max_wide_height = Rational { + numerator: 172, + denominator: 540, + }; + let ideal_panel_height = Rational { + numerator: ideal_height_px as i32, + denominator: dbg!(px_size.width), + }; // Reduce height to match what the layout can fill. - // For this, we need to guess if normal or wide will be picked up. + // For this, we need to guess if normal or wide will be picked. // This must match `eek_gtk_keyboard.c::get_type`. // TODO: query layout database and choose one directly - let abstract_width - = PixelSize { - scale_factor: output.scale as u32, - pixels: px_size.width, - } - .as_scaled_ceiling(); - let (arrangement, height_as_widths) = { - if abstract_width < 540 {( + if max_wide_height < dbg!(ideal_panel_height) {( ArrangementKind::Base, Rational { numerator: 210, @@ -405,16 +406,13 @@ Outcome: }, )} else {( ArrangementKind::Wide, - Rational { - numerator: 172, - denominator: 540, - } + max_wide_height, )} }; let height = cmp::min( - ideal_height_px, + dbg!(ideal_height_px), (height_as_widths * px_size.width as i32).ceil() as u32, ); @@ -755,4 +753,33 @@ pub mod test { )), ); } + + + #[test] + fn size_l5_scale1() { + use crate::outputs::{Mode, Geometry, c, Size}; + assert_eq!( + Application::get_preferred_height_and_arrangement(&OutputState { + current_mode: Some(Mode { + width: 720, + height: 1440, + }), + geometry: Some(Geometry{ + transform: c::Transform::Normal, + phys_size: Size { + width: Some(Millimeter(65)), + height: Some(Millimeter(130)), + }, + }), + scale: 1, + }), + Some(( + PixelSize { + scale_factor: 1, + pixels: 420, + }, + ArrangementKind::Base, + )), + ); + } } diff --git a/src/util.rs b/src/util.rs index 0b99ea88..d96f69e6 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,6 +4,7 @@ use std::rc::Rc; use crate::float_ord::FloatOrd; use std::borrow::Borrow; +use std::cmp::{Ordering, PartialOrd}; use std::hash::{ Hash, Hasher }; use std::ops::Mul; @@ -242,6 +243,34 @@ impl> Mul> for Rational { } } +impl PartialEq for Rational { + fn eq(&self, other: &Self) -> bool { + (self.denominator as i64).saturating_mul(other.numerator as i64) + == (other.denominator as i64).saturating_mul(self.numerator as i64) + } +} + +impl Eq for Rational {} + +impl Ord for Rational { + fn cmp(&self, other: &Self) -> Ordering { + // Using 64-bit values to make overflows unlikely. + // If i32_max * u32_max can exceed i64_max, + // then this is actually PartialOrd. + // Saturating mul used just to avoid propagating mistakes. + (other.denominator as i64).saturating_mul(self.numerator as i64) + .cmp( + &(self.denominator as i64).saturating_mul(other.numerator as i64) + ) + } +} + +impl PartialOrd for Rational { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + /// Compares pointers but not internal values of Rc pub struct Pointer(pub Rc); @@ -327,4 +356,20 @@ mod tests { vec![(5, 0), (6, 0), (7, 0), (5, 1), (6, 1), (7, 1), (5, 2)] ); } + + #[test] + fn check_rational_cmp() { + assert_eq!( + Rational { numerator: 1, denominator: 1 }, + Rational { numerator: 1, denominator: 1 }, + ); + assert_eq!( + Rational { numerator: 1, denominator: 1 }, + Rational { numerator: 2, denominator: 2 }, + ); + assert!( + Rational { numerator: 1, denominator: 1 } + < Rational { numerator: 2, denominator: 1 } + ); + } }