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 {
|
if focused_surface == *surface {
|
||||||
let current = pointer.current_location();
|
let current = pointer.current_location();
|
||||||
let scale = self
|
let (scale_x, scale_y) = self
|
||||||
.window_under_visual(current)
|
.window_under_visual(current)
|
||||||
.and_then(|window| self.visual_scale_for_window(&window))
|
.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 current_surface_location = current - origin;
|
||||||
let offset = location - current_surface_location;
|
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 pointer = self.seat.get_pointer().expect("seat has a pointer");
|
||||||
let position = pointer.current_location();
|
let position = pointer.current_location();
|
||||||
let focus = self.surface_under(position);
|
let focus = self.surface_under(position);
|
||||||
let scale = self
|
let (scale_x, scale_y) = self
|
||||||
.window_under_visual(position)
|
.window_under_visual(position)
|
||||||
.and_then(|window| self.visual_scale_for_window(&window))
|
.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 = event.delta();
|
||||||
let delta_unaccel = event.delta_unaccel();
|
let delta_unaccel = event.delta_unaccel();
|
||||||
|
|
||||||
@@ -185,8 +185,9 @@ impl Ferese {
|
|||||||
self,
|
self,
|
||||||
focus,
|
focus,
|
||||||
&RelativeMotionEvent {
|
&RelativeMotionEvent {
|
||||||
delta: (delta.x / scale, delta.y / scale).into(),
|
delta: (delta.x / scale_x, delta.y / scale_y).into(),
|
||||||
delta_unaccel: (delta_unaccel.x / scale, delta_unaccel.y / scale).into(),
|
delta_unaccel: (delta_unaccel.x / scale_x, delta_unaccel.y / scale_y)
|
||||||
|
.into(),
|
||||||
utime: (event.time_msec() as u64).saturating_mul(1_000),
|
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)?;
|
let id = self.window_ids.get(window)?;
|
||||||
self.window_geometry.get(id)?.visual_scale()
|
self.window_geometry.get(id)?.visual_scale()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ pub(crate) fn animated_window_elements(
|
|||||||
constrain,
|
constrain,
|
||||||
ConstrainBehavior {
|
ConstrainBehavior {
|
||||||
reference: ConstrainReference::Geometry,
|
reference: ConstrainReference::Geometry,
|
||||||
behavior: ConstrainScaleBehavior::Zoom,
|
behavior: ConstrainScaleBehavior::Stretch,
|
||||||
align: ConstrainAlign::TOP | ConstrainAlign::LEFT,
|
align: ConstrainAlign::TOP | ConstrainAlign::LEFT,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -237,19 +237,22 @@ impl WindowGeometry {
|
|||||||
|
|
||||||
pub fn inverse_visual_point(&self, x: f64, y: f64) -> Option<(f64, f64)> {
|
pub fn inverse_visual_point(&self, x: f64, y: f64) -> Option<(f64, f64)> {
|
||||||
let visual = self.visual.current;
|
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 source = self.client.committed_size?;
|
||||||
let visual = self.visual.current;
|
let visual = self.visual.current;
|
||||||
if source.width <= 0 || source.height <= 0 || visual.width <= 0.0 || visual.height <= 0.0 {
|
if source.width <= 0 || source.height <= 0 || visual.width <= 0.0 || visual.height <= 0.0 {
|
||||||
return None;
|
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]
|
#[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 initial = Rect::new(100.0, 50.0, 400.0, 300.0);
|
||||||
let mut geometry = WindowGeometry::new(initial, Some(ClientSize::from_rect(initial)));
|
let mut geometry = WindowGeometry::new(initial, Some(ClientSize::from_rect(initial)));
|
||||||
geometry.visual.current = Rect::new(200.0, 100.0, 600.0, 600.0);
|
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!(
|
assert_eq!(
|
||||||
geometry.inverse_visual_point(600.0, 500.0),
|
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
|
buffer or snapshot, client content MUST remain aligned with the visual geometry
|
||||||
used for hit testing.
|
used for hit testing.
|
||||||
|
|
||||||
During a non-interactive resize, committed content is scaled uniformly to cover
|
During a non-interactive resize, committed content is scaled independently on
|
||||||
the visual content box and clipped to that box, anchored at its top-left content
|
each axis to fill the visual content box and clipped to that box, anchored at
|
||||||
origin. Ferese MUST NOT expose uninitialized regions. When a matching commit
|
its top-left content origin. This avoids the oversized crop produced by uniform
|
||||||
arrives it replaces the scaled source without restarting the animation. A commit
|
cover scaling when only one dimension changes. Ferese MUST NOT expose
|
||||||
is matching when its acknowledged configure and effective buffer geometry match
|
uninitialized regions. When a matching commit arrives it replaces the scaled
|
||||||
the requested client size after scale and transform.
|
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
|
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,
|
ms, Ferese MUST stop waiting for visual completion, retain the target layout,
|
||||||
|
|||||||
Reference in new issue
Block a user