fix: tame animated resize scaling
This commit is contained in:
1 parent
f6dce3316a
commit
bf4f5f77f7
6 files changed
+27
-22
No files matched your search
@@ -194,14 +194,14 @@ impl PointerConstraintsHandler for Ferese {
|
||||
};
|
||||
if focused_surface == *surface {
|
||||
let current = pointer.current_location();
|
||||
let scale = self
|
||||
let (scale_x, scale_y) = self
|
||||
.window_under_visual(current)
|
||||
.and_then(|window| self.visual_scale_for_window(&window))
|
||||
.unwrap_or(1.0);
|
||||
.unwrap_or((1.0, 1.0));
|
||||
let current_surface_location = current - origin;
|
||||
let offset = location - current_surface_location;
|
||||
|
||||
pointer.set_location(current + Point::from((offset.x * scale, offset.y * scale)));
|
||||
pointer.set_location(current + Point::from((offset.x * scale_x, offset.y * scale_y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +174,10 @@ impl Ferese {
|
||||
let pointer = self.seat.get_pointer().expect("seat has a pointer");
|
||||
let position = pointer.current_location();
|
||||
let focus = self.surface_under(position);
|
||||
let scale = self
|
||||
let (scale_x, scale_y) = self
|
||||
.window_under_visual(position)
|
||||
.and_then(|window| self.visual_scale_for_window(&window))
|
||||
.unwrap_or(1.0);
|
||||
.unwrap_or((1.0, 1.0));
|
||||
let delta = event.delta();
|
||||
let delta_unaccel = event.delta_unaccel();
|
||||
|
||||
@@ -185,8 +185,9 @@ impl Ferese {
|
||||
self,
|
||||
focus,
|
||||
&RelativeMotionEvent {
|
||||
delta: (delta.x / scale, delta.y / scale).into(),
|
||||
delta_unaccel: (delta_unaccel.x / scale, delta_unaccel.y / scale).into(),
|
||||
delta: (delta.x / scale_x, delta.y / scale_y).into(),
|
||||
delta_unaccel: (delta_unaccel.x / scale_x, delta_unaccel.y / scale_y)
|
||||
.into(),
|
||||
utime: (event.time_msec() as u64).saturating_mul(1_000),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -332,7 +332,7 @@ impl Ferese {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn visual_scale_for_window(&self, window: &Window) -> Option<f64> {
|
||||
pub fn visual_scale_for_window(&self, window: &Window) -> Option<(f64, f64)> {
|
||||
let id = self.window_ids.get(window)?;
|
||||
self.window_geometry.get(id)?.visual_scale()
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ pub(crate) fn animated_window_elements(
|
||||
constrain,
|
||||
ConstrainBehavior {
|
||||
reference: ConstrainReference::Geometry,
|
||||
behavior: ConstrainScaleBehavior::Zoom,
|
||||
behavior: ConstrainScaleBehavior::Stretch,
|
||||
align: ConstrainAlign::TOP | ConstrainAlign::LEFT,
|
||||
},
|
||||
))
|
||||
|
||||
@@ -237,19 +237,22 @@ impl WindowGeometry {
|
||||
|
||||
pub fn inverse_visual_point(&self, x: f64, y: f64) -> Option<(f64, f64)> {
|
||||
let visual = self.visual.current;
|
||||
let scale = self.visual_scale()?;
|
||||
let (scale_x, scale_y) = self.visual_scale()?;
|
||||
|
||||
Some(((x - visual.x) / scale, (y - visual.y) / scale))
|
||||
Some(((x - visual.x) / scale_x, (y - visual.y) / scale_y))
|
||||
}
|
||||
|
||||
pub fn visual_scale(&self) -> Option<f64> {
|
||||
pub fn visual_scale(&self) -> Option<(f64, f64)> {
|
||||
let source = self.client.committed_size?;
|
||||
let visual = self.visual.current;
|
||||
if source.width <= 0 || source.height <= 0 || visual.width <= 0.0 || visual.height <= 0.0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((visual.width / f64::from(source.width)).max(visual.height / f64::from(source.height)))
|
||||
Some((
|
||||
visual.width / f64::from(source.width),
|
||||
visual.height / f64::from(source.height),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,15 +384,14 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inverse_visual_point_matches_uniform_cover_transform() {
|
||||
fn inverse_visual_point_matches_stretched_transform() {
|
||||
let initial = Rect::new(100.0, 50.0, 400.0, 300.0);
|
||||
let mut geometry = WindowGeometry::new(initial, Some(ClientSize::from_rect(initial)));
|
||||
geometry.visual.current = Rect::new(200.0, 100.0, 600.0, 600.0);
|
||||
|
||||
// Cover scales the 4:3 source by 2x for a square allocation, then clips it.
|
||||
assert_eq!(
|
||||
geometry.inverse_visual_point(600.0, 500.0),
|
||||
Some((200.0, 200.0))
|
||||
Some((400.0 * 2.0 / 3.0, 200.0))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -549,12 +549,14 @@ to avoid a visible source-size discontinuity. Whether using a live committed
|
||||
buffer or snapshot, client content MUST remain aligned with the visual geometry
|
||||
used for hit testing.
|
||||
|
||||
During a non-interactive resize, committed content is scaled uniformly to cover
|
||||
the visual content box and clipped to that box, anchored at its top-left content
|
||||
origin. Ferese MUST NOT expose uninitialized regions. When a matching commit
|
||||
arrives it replaces the scaled source without restarting the animation. A commit
|
||||
is matching when its acknowledged configure and effective buffer geometry match
|
||||
the requested client size after scale and transform.
|
||||
During a non-interactive resize, committed content is scaled independently on
|
||||
each axis to fill the visual content box and clipped to that box, anchored at
|
||||
its top-left content origin. This avoids the oversized crop produced by uniform
|
||||
cover scaling when only one dimension changes. Ferese MUST NOT expose
|
||||
uninitialized regions. When a matching commit arrives it replaces the scaled
|
||||
source without restarting the animation. A commit is matching when its
|
||||
acknowledged configure and effective buffer geometry match the requested client
|
||||
size after scale and transform.
|
||||
|
||||
If a client has not acknowledged and committed the final configure within 500
|
||||
ms, Ferese MUST stop waiting for visual completion, retain the target layout,
|
||||
|
||||
Reference in new issue
Block a user