Synchronize shell material presentation with surface commits
Queue popup, modal and notification material geometry and opacity until the matching content buffer commits. Remove event-handler opacity writes that could present material state ahead of content, while preserving compositor dismissal ownership. Add pending-presentation regression coverage and update the nested shell lifecycle check.
This commit is contained in:
1 parent
e6e1a2a8cf
commit
bffd538dd4
9 files changed
+159
-50
No files matched your search
@@ -524,12 +524,14 @@ impl FereseShell {
|
||||
if let Some(surface) = &self.notification_surface
|
||||
&& let Some(effects) = &surface.effects
|
||||
{
|
||||
let _ = effects.set_regions(&surface.regions.lock().unwrap());
|
||||
let _ = effects.set_region_opacities(
|
||||
let _ = effects.set_presentation(
|
||||
&surface.regions.lock().unwrap(),
|
||||
1.0,
|
||||
self.notifications
|
||||
.popup_groups_at(now)
|
||||
.iter()
|
||||
.map(|(_, opacity, _)| *opacity),
|
||||
ferese_surface_effects_v1::Role::Popover,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -145,9 +145,6 @@ impl FereseShell {
|
||||
|
||||
pub fn animate_menu(&mut self) -> Task<Message> {
|
||||
if let Some(menu) = &self.menu {
|
||||
if let Some(effects) = &menu.effects {
|
||||
let _ = effects.set_opacity(menu.progress().clamp(0.0, 1.0));
|
||||
}
|
||||
if menu.motion.closing() && !menu.animating() {
|
||||
return self.destroy_menu();
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ impl OpenMenu {
|
||||
super::EFFECT_FRAME_PENDING.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn progress(&self) -> f32 {
|
||||
self.motion.progress()
|
||||
}
|
||||
@@ -138,8 +139,12 @@ impl FereseShell {
|
||||
|now| menu.motion.frame_active(now),
|
||||
|now| {
|
||||
if let Some(effects) = &menu.effects {
|
||||
let _ = effects.set_regions(&menu.regions.lock().unwrap());
|
||||
let _ = effects.set_opacity(menu.motion.progress_at(now).clamp(0.0, 1.0));
|
||||
let _ = effects.set_presentation(
|
||||
&menu.regions.lock().unwrap(),
|
||||
menu.motion.progress_at(now),
|
||||
[],
|
||||
super::ferese_surface_effects_v1::Role::Popover,
|
||||
);
|
||||
}
|
||||
},
|
||||
|now| {
|
||||
|
||||
@@ -333,9 +333,6 @@ impl FereseShell {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(effects) = &menu.effects {
|
||||
let _ = effects.set_opacity(menu.progress());
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
@@ -488,7 +485,7 @@ pub(super) struct EffectsBinding {
|
||||
_queue: EventQueue<EffectsState>,
|
||||
regions: std::cell::RefCell<Option<Vec<[f32; 5]>>>,
|
||||
opacity: std::cell::Cell<Option<u32>>,
|
||||
region_opacities: std::cell::RefCell<Vec<u32>>,
|
||||
presentation: std::cell::RefCell<Option<(Vec<[f32; 5]>, u32, Vec<u32>, ferese_surface_effects_v1::Role)>>,
|
||||
}
|
||||
|
||||
impl EffectsBinding {
|
||||
@@ -512,7 +509,7 @@ 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, 4..=4, ())?;
|
||||
let manager = globals.bind::<FereseEffectsManagerV1, _, _>(&qh, 5..=5, ())?;
|
||||
let effects = manager.get_surface_effects(surface, &qh, ());
|
||||
|
||||
let opacity = (opacity.clamp(0.0, 1.0) * 1000.0).round() as u32;
|
||||
@@ -531,24 +528,33 @@ impl EffectsBinding {
|
||||
_queue: queue,
|
||||
regions: Default::default(),
|
||||
opacity: std::cell::Cell::new(Some(opacity)),
|
||||
region_opacities: Default::default(),
|
||||
presentation: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn set_region_opacities(
|
||||
pub(super) fn set_presentation(
|
||||
&self,
|
||||
values: impl IntoIterator<Item = f32>,
|
||||
regions: &[[f32; 5]],
|
||||
opacity: f32,
|
||||
region_opacities: impl IntoIterator<Item = f32>,
|
||||
role: ferese_surface_effects_v1::Role,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let values: Vec<u32> = values
|
||||
let opacity = (opacity.clamp(0.0, 1.0) * 1000.0).round() as u32;
|
||||
let values: Vec<u32> = region_opacities
|
||||
.into_iter()
|
||||
.take(32)
|
||||
.map(|value| (value.clamp(0.0, 1.0) * 1000.0).round() as u32)
|
||||
.collect();
|
||||
if *self.region_opacities.borrow() != values {
|
||||
self.surface
|
||||
.set_region_opacities(values.iter().flat_map(|value| value.to_ne_bytes()).collect());
|
||||
let next = (regions.to_vec(), opacity, values, role);
|
||||
if self.presentation.borrow().as_ref() != Some(&next) {
|
||||
self.surface.set_presentation(
|
||||
role,
|
||||
encode_regions(regions),
|
||||
opacity,
|
||||
next.2.iter().flat_map(|value| value.to_ne_bytes()).collect(),
|
||||
);
|
||||
self.connection.flush()?;
|
||||
*self.region_opacities.borrow_mut() = values;
|
||||
*self.presentation.borrow_mut() = Some(next);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -291,18 +291,6 @@ impl FereseShell {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn update_power_materials(&self) {
|
||||
if let Some(modal) = &self.system_modal {
|
||||
for entry in &modal.surfaces {
|
||||
if let Some(effects) = &entry.effects {
|
||||
let regions = entry.regions.lock().unwrap().clone();
|
||||
let _ = effects.set_material_regions(®ions, ferese_surface_effects_v1::Role::Modal);
|
||||
let _ = effects.set_opacity(modal.motion.progress().clamp(0.0, 1.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn close_system_modal(&mut self) -> Task<Message> {
|
||||
if self.system_modal.as_ref().is_some_and(SystemModal::is_display_mode) {
|
||||
if self.display_mode.busy {
|
||||
@@ -339,7 +327,6 @@ impl FereseShell {
|
||||
{
|
||||
return self.destroy_system_modal(false);
|
||||
}
|
||||
self.update_power_materials();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
@@ -483,9 +470,12 @@ impl FereseShell {
|
||||
|now| modal.motion.frame_active(now),
|
||||
|now| {
|
||||
if let Some(effects) = &surface.effects {
|
||||
let _ = effects
|
||||
.set_material_regions(&surface.regions.lock().unwrap(), ferese_surface_effects_v1::Role::Modal);
|
||||
let _ = effects.set_opacity(modal.motion.progress_at(now).clamp(0.0, 1.0));
|
||||
let _ = effects.set_presentation(
|
||||
&surface.regions.lock().unwrap(),
|
||||
modal.motion.progress_at(now),
|
||||
[],
|
||||
ferese_surface_effects_v1::Role::Modal,
|
||||
);
|
||||
}
|
||||
},
|
||||
|now| {
|
||||
|
||||
Reference in new issue
Block a user