Align corner clipping, antialiasing, and fractional material regions
This commit is contained in:
1 parent
f110ec80e1
commit
9666e4ff6c
16 files changed
+237
-68
No files matched your search
@@ -3,7 +3,7 @@ use cosmic::iced::advanced::{Clipboard, Layout, Renderer as _, Shell, Widget, la
|
||||
use cosmic::iced::{Event, Length, Rectangle, Size, Transformation, Vector};
|
||||
use cosmic::{Element, Theme};
|
||||
|
||||
pub type Regions = std::sync::Arc<std::sync::Mutex<Vec<[i32; 5]>>>;
|
||||
pub type Regions = std::sync::Arc<std::sync::Mutex<Vec<[f32; 5]>>>;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, serde::Deserialize)]
|
||||
#[serde(default)]
|
||||
@@ -463,18 +463,18 @@ impl<M> Widget<M, Theme, cosmic::Renderer> for Motion<'_, M> {
|
||||
struct CollectRegions(Vec<Rectangle>);
|
||||
|
||||
impl CollectRegions {
|
||||
fn into_regions(self, translation: Vector, radius: f32) -> Vec<[i32; 5]> {
|
||||
fn into_regions(self, translation: Vector, radius: f32) -> Vec<[f32; 5]> {
|
||||
self.0
|
||||
.into_iter()
|
||||
.take(32)
|
||||
.filter(|r| r.width > 0.0 && r.height > 0.0)
|
||||
.map(|r| {
|
||||
[
|
||||
(r.x + translation.x).round() as i32,
|
||||
(r.y + translation.y).round() as i32,
|
||||
r.width.round() as i32,
|
||||
r.height.round() as i32,
|
||||
radius.round().max(0.0) as i32,
|
||||
r.x + translation.x,
|
||||
r.y + translation.y,
|
||||
r.width,
|
||||
r.height,
|
||||
radius.max(0.0),
|
||||
]
|
||||
})
|
||||
.collect()
|
||||
@@ -508,6 +508,15 @@ impl widget::Operation for CollectRegions {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn material_regions_preserve_fractional_layout_and_translation() {
|
||||
let collector = CollectRegions(vec![Rectangle::new((0.25, 2.5).into(), (100.25, 40.5).into())]);
|
||||
assert_eq!(
|
||||
collector.into_regions(Vector::new(0.125, -0.25), 13.5),
|
||||
vec![[0.375, 2.25, 100.25, 40.5, 13.5]]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn centered_modal_material_tracks_surface_position_and_animation() {
|
||||
let mut collector = CollectRegions(Vec::new());
|
||||
@@ -515,7 +524,7 @@ mod tests {
|
||||
widget::Operation::container(&mut collector, Some(&widget::Id::new("ferese-blur-card")), card);
|
||||
assert_eq!(
|
||||
collector.into_regions(Vector::new(0.0, -2.0), 14.0),
|
||||
vec![[380, 418, 440, 220, 14]]
|
||||
vec![[380., 418., 440., 220., 14.]]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -467,6 +467,7 @@ impl FereseShell {
|
||||
width: if history { 0.0 } else { 1.0 },
|
||||
radius: palette.material_radius.into(),
|
||||
},
|
||||
snap: true,
|
||||
..Default::default()
|
||||
}));
|
||||
let card: Element<'_, cosmic::Action<Message>> = card.into();
|
||||
@@ -738,6 +739,7 @@ impl FereseShell {
|
||||
width: 1.0,
|
||||
radius: palette.material_radius.into(),
|
||||
},
|
||||
snap: true,
|
||||
..Default::default()
|
||||
}))
|
||||
.into();
|
||||
|
||||
@@ -222,6 +222,7 @@ impl FereseShell {
|
||||
width: 1.0,
|
||||
radius: theme.material_radius.into(),
|
||||
},
|
||||
snap: true,
|
||||
..Default::default()
|
||||
}));
|
||||
|
||||
|
||||
@@ -433,12 +433,19 @@ pub(super) fn wallpaper_fallback_style(_theme: &cosmic::Theme) -> container::Sty
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_regions(regions: &[[f32; 5]]) -> Vec<u8> {
|
||||
regions
|
||||
.iter()
|
||||
.flat_map(|region| region.iter().flat_map(|value| value.to_ne_bytes()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(super) struct EffectsBinding {
|
||||
connection: Connection,
|
||||
_manager: FereseEffectsManagerV1,
|
||||
pub(super) surface: FereseSurfaceEffectsV1,
|
||||
_queue: EventQueue<EffectsState>,
|
||||
regions: std::cell::RefCell<Option<Vec<[i32; 5]>>>,
|
||||
regions: std::cell::RefCell<Option<Vec<[f32; 5]>>>,
|
||||
opacity: std::cell::Cell<Option<u32>>,
|
||||
}
|
||||
|
||||
@@ -463,13 +470,11 @@ impl EffectsBinding {
|
||||
let connection = Connection::from_backend(backend);
|
||||
let (globals, queue) = registry_queue_init::<EffectsState>(&connection)?;
|
||||
let qh = queue.handle();
|
||||
let manager = globals.bind::<FereseEffectsManagerV1, _, _>(&qh, 1..=3, ())?;
|
||||
let manager = globals.bind::<FereseEffectsManagerV1, _, _>(&qh, 3..=3, ())?;
|
||||
let effects = manager.get_surface_effects(surface, &qh, ());
|
||||
|
||||
let opacity = (opacity.clamp(0.0, 1.0) * 1000.0).round() as u32;
|
||||
if effects.version() >= 3 {
|
||||
effects.set_opacity(opacity);
|
||||
}
|
||||
effects.set_opacity(opacity);
|
||||
if let Some(role) = role {
|
||||
effects.set_role(role);
|
||||
} else {
|
||||
@@ -487,24 +492,19 @@ impl EffectsBinding {
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn set_regions(&self, regions: &[[i32; 5]]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
pub(super) fn set_regions(&self, regions: &[[f32; 5]]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
self.set_material_regions(regions, ferese_surface_effects_v1::Role::Popover)
|
||||
}
|
||||
|
||||
pub(super) fn set_material_regions(
|
||||
&self,
|
||||
regions: &[[i32; 5]],
|
||||
regions: &[[f32; 5]],
|
||||
role: ferese_surface_effects_v1::Role,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if self.surface.version() < 2 || self.regions.borrow().as_deref() == Some(regions) {
|
||||
if self.regions.borrow().as_deref() == Some(regions) {
|
||||
return Ok(());
|
||||
}
|
||||
self.surface.set_regions(
|
||||
regions
|
||||
.iter()
|
||||
.flat_map(|r| r.iter().flat_map(|v| v.to_ne_bytes()))
|
||||
.collect(),
|
||||
);
|
||||
self.surface.set_regions(encode_regions(regions));
|
||||
if regions.is_empty() {
|
||||
self.surface.clear_role();
|
||||
} else {
|
||||
@@ -529,7 +529,7 @@ impl EffectsBinding {
|
||||
|
||||
pub(super) fn set_opacity(&self, opacity: f32) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let opacity = (opacity.clamp(0.0, 1.0) * 1000.0).round() as u32;
|
||||
if self.surface.version() >= 3 && self.opacity.get() != Some(opacity) {
|
||||
if self.opacity.get() != Some(opacity) {
|
||||
self.surface.set_opacity(opacity);
|
||||
self.connection.flush()?;
|
||||
self.opacity.set(Some(opacity));
|
||||
@@ -554,3 +554,17 @@ impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for EffectsState {
|
||||
|
||||
delegate_noop!(EffectsState: ignore FereseEffectsManagerV1);
|
||||
delegate_noop!(EffectsState: ignore FereseSurfaceEffectsV1);
|
||||
|
||||
#[cfg(test)]
|
||||
mod region_encoding_tests {
|
||||
#[test]
|
||||
fn fractional_region_encoding_preserves_values() {
|
||||
let regions = [[0.25, -0.75, 100.5, 40.25, 14.0]];
|
||||
let bytes = super::encode_regions(®ions);
|
||||
let decoded: Vec<_> = bytes
|
||||
.chunks_exact(4)
|
||||
.map(|v| f32::from_ne_bytes(v.try_into().unwrap()))
|
||||
.collect();
|
||||
assert_eq!(decoded, regions[0]);
|
||||
}
|
||||
}
|
||||
@@ -541,6 +541,7 @@ impl FereseShell {
|
||||
width: 1.0,
|
||||
radius: theme.material_radius.into(),
|
||||
},
|
||||
snap: true,
|
||||
..Default::default()
|
||||
}))
|
||||
.into()
|
||||
|
||||
Reference in new issue
Block a user