diff --git a/core/src/fixed.rs b/core/src/fixed.rs index 1850ac1..8da9d48 100644 --- a/core/src/fixed.rs +++ b/core/src/fixed.rs @@ -131,14 +131,6 @@ impl Fixed { self.0 as f32 / Self::one().0 as f32 } - /// The same value on another grid, rounded where the new one is coarser. - pub const fn to_scale(self) -> Fixed { - Fixed(match TO >= SHIFT { - true => self.0 << (TO - SHIFT), - false => shift_round(self.0 as i64, SHIFT - TO) as i32, - }) - } - pub const fn add(self, rhs: Self) -> Self { Self(self.0.wrapping_add(rhs.0)) } @@ -246,16 +238,6 @@ impl Fixed { } } -/// Back to a single step, rounding halves away from zero so that a value and -/// its negation round to the same distance. -const fn shift_round(v: i64, bits: u32) -> i64 { - let half = (1i64 << bits) >> 1; - match v < 0 { - true => -((-v + half) >> bits), - false => (v + half) >> bits, - } -} - const fn div_round(num: i64, den: i64) -> i64 { let (q, rem) = (num / den, num % den); match rem.unsigned_abs() * 2 >= den.unsigned_abs() { @@ -531,15 +513,6 @@ mod tests { assert_eq!(Px::from_f32(-1e12), Px::MIN); } - #[test] - fn a_coarser_grid_rounds_and_a_finer_one_does_not() { - // A third, which neither grid holds exactly. - let third = Rel::ONE / Rel::from_int(3); - assert_eq!(third.to_scale::<6>(), Fixed::<6>::from_raw(21)); - let coarse = Fixed::<6>::from_raw(21); - assert_eq!(coarse.to_scale::<24>().to_scale::<6>(), coarse); - } - #[test] fn lerp_takes_the_fraction_as_the_receiver() { let (from, to) = (Px::from_int(10), Px::from_int(20)); diff --git a/core/src/orientation/align.rs b/core/src/orientation/align.rs index 605fcc8..99d952b 100644 --- a/core/src/orientation/align.rs +++ b/core/src/orientation/align.rs @@ -151,13 +151,15 @@ impl Vec2 { } impl Len { + /// This length placed in the box it is measured in: the alignment names a + /// point along that box, and the two ends are that point less the part of + /// the length falling before it and plus the part falling after. pub const fn align(&self, align: AxisAlign) -> UiSpan { let rel = align.rel(); - let rest = Rel::ONE.sub(rel); let at = Len::from_parts(rel, Px::ZERO); UiSpan { - start: Len::from_parts(at.rel.sub(self.rel.mul(rel)), at.px.sub(self.px.mul(rel))), - end: Len::from_parts(at.rel.add(self.rel.mul(rest)), at.px.add(self.px.mul(rest))), + start: at - self.scale(rel), + end: at + self.scale(Rel::ONE.sub(rel)), } } } diff --git a/core/src/orientation/len.rs b/core/src/orientation/len.rs index 7c31074..0ef6bdc 100644 --- a/core/src/orientation/len.rs +++ b/core/src/orientation/len.rs @@ -169,7 +169,7 @@ impl LayoutLen { /// anyone not dividing a box between siblings, where a share is a claim /// on someone else's room rather than a length of its own. /// [`Self::apply_leftover`] is the opposite reading of the same value. - pub const fn without_leftover(self) -> Len { + pub const fn without_leftover(&self) -> Len { Len::from_parts(self.rel, self.px) } diff --git a/scripts/run-headless.sh b/scripts/run-headless.sh index b2081c8..d46d393 100755 --- a/scripts/run-headless.sh +++ b/scripts/run-headless.sh @@ -106,11 +106,16 @@ export WAYLAND_DISPLAY echo "run-headless: $WAYLAND_DISPLAY (sway $(swaymsg -t get_version --raw | sed -n 's/.*"human_readable":"\([^"]*\)".*/\1/p'))" >&2 -swaymsg output HEADLESS-1 mode "$mode" >/dev/null -# The extent `replay-touch` positions against, so a script's coordinates -# are the output's own pixels. -out_w=${mode%x*} -out_h=${mode#*x}; out_h=${out_h%@*} +# The extent `replay-touch` positions against, so a script's coordinates are +# the output's own pixels. Set beside every mode change, since a gesture +# scaled against a mode the output no longer has lands somewhere else and +# still looks like a run that worked. +set_mode() { + swaymsg output HEADLESS-1 mode "$1" >/dev/null + out_w=${1%x*} + out_h=${1#*x}; out_h=${out_h%@*} +} +set_mode "$mode" # Built before the app starts, so a compile error is not reported as a # window that failed to move. @@ -149,7 +154,7 @@ while [ $i -lt "$((seconds * 2))" ]; do done if [ -n "$resize" ] && kill -0 "$pid" 2>/dev/null; then - swaymsg output HEADLESS-1 mode "$resize" >/dev/null + set_mode "$resize" echo "run-headless: resized to $resize" >&2 sleep 2 fi diff --git a/src/random.rs b/src/random.rs index 2f37937..f4e06cf 100644 --- a/src/random.rs +++ b/src/random.rs @@ -773,10 +773,6 @@ impl Sow<'_> { self.spans += 1; let edit = self.edits.spans.get(&idx).cloned().unwrap_or_default(); let dir = self.rng.below(4); - // A row takes the height it is given rather than its tallest child, - // which is a rule beside it. Derived from an existing choice and - // consuming no randomness: a seed must keep growing the same tree - // when the generator gains another configuration. let gap = self.rng.below(3) as i32 * 4; let grown: Vec = (0..children.len()).collect(); let order = span_edited(&grown, children.len(), spares.len(), &edit); @@ -915,6 +911,10 @@ impl Build<'_, Rsc> { gap: Px::from_int(*gap), } .add(self.rsc); + // A row takes the height it is given rather than its tallest + // child, which is a rule beside the span rather than anything + // it draws. Derived from `dir` rather than stored, so a plan + // that says the direction says this too. if dir.axis == Axis::X { self.rsc .widgets_mut() diff --git a/src/widget/position/scroll.rs b/src/widget/position/scroll.rs index 788f355..fe44ac2 100644 --- a/src/widget/position/scroll.rs +++ b/src/widget/position/scroll.rs @@ -45,13 +45,14 @@ impl Widget for Scroll { painter.holds(self.axis, Px::MIN..=left); } - // Content that fills the viewport and has not been scrolled is the - // viewport, and is handed back as it came. Writing the same box as - // its own length in pixels is the same box in another form, and the - // two do not round alike: a part centred in `rel 1` lands a step from - // one centred in `px 900`, since halving a difference is not halving - // each part of it. - let content = match self.amt != Px::ZERO || self.content_len != self.container_len { + // Content that fills the viewport is the viewport, and is handed back + // as it came -- it has nothing to scroll through, so the clamp above + // has already put `amt` at zero. Writing the same box as its own + // length in pixels is the same box in another form, and the two do + // not round alike: a part centred in `rel 1` lands a step from one + // centred in `px 900`, since halving a difference is not halving each + // part of it. + let content = match self.content_len > self.container_len { true => { let start = Len::from_parts(Rel::ZERO, -self.amt); UiSpan::new(start, start.offset(self.content_len)).shifted_desc()