fix: unify animated presentation and stacking
This commit is contained in:
1 parent
83e36b0d2d
commit
6d19932a64
11 files changed
+484
-107
No files matched your search
@@ -7,7 +7,7 @@ use smithay::{
|
||||
PointerInnerHandle, RelativeMotionEvent,
|
||||
},
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
utils::{Logical, Point},
|
||||
utils::{Logical, Point, Size},
|
||||
};
|
||||
|
||||
use crate::Ferese;
|
||||
@@ -16,6 +16,7 @@ pub struct MoveSurfaceGrab {
|
||||
pub start_data: GrabStartData<Ferese>,
|
||||
pub window: Window,
|
||||
pub initial_location: Point<i32, Logical>,
|
||||
pub initial_size: Size<i32, Logical>,
|
||||
pub finished: bool,
|
||||
}
|
||||
|
||||
@@ -30,10 +31,7 @@ impl PointerGrab<Ferese> for MoveSurfaceGrab {
|
||||
handle.motion(data, None, event);
|
||||
let location = self.initial_location.to_f64() + (event.location - self.start_data.location);
|
||||
let location = location.to_i32_round();
|
||||
let size = self.window.geometry().size;
|
||||
|
||||
data.set_floating_window_geometry(&self.window, location, size);
|
||||
data.space.map_element(self.window.clone(), location, true);
|
||||
data.set_floating_window_geometry(&self.window, location, self.initial_size);
|
||||
}
|
||||
|
||||
fn relative_motion(
|
||||
@@ -153,9 +151,6 @@ impl PointerGrab<Ferese> for MoveSurfaceGrab {
|
||||
return;
|
||||
}
|
||||
|
||||
let size = self.window.geometry().size;
|
||||
data.set_floating_window_geometry(&self.window, self.initial_location, size);
|
||||
data.space
|
||||
.map_element(self.window.clone(), self.initial_location, true);
|
||||
data.set_floating_window_geometry(&self.window, self.initial_location, self.initial_size);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use smithay::{
|
||||
desktop::{Space, Window},
|
||||
desktop::Window,
|
||||
input::pointer::{
|
||||
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
|
||||
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
|
||||
@@ -275,8 +275,6 @@ impl PointerGrab<Ferese> for ResizeSurfaceGrab {
|
||||
self.initial_rect.loc,
|
||||
self.initial_rect.size,
|
||||
);
|
||||
data.space
|
||||
.map_element(self.window.clone(), self.initial_rect.loc, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,35 +324,10 @@ impl ResizeState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_resize_commit(space: &mut Space<Window>, surface: &WlSurface) {
|
||||
let Some(window) = space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == surface)
|
||||
})
|
||||
.cloned()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(mut location) = space.element_location(&window) else {
|
||||
return;
|
||||
};
|
||||
let geometry = window.geometry();
|
||||
let Some((edges, initial_rect)) = ResizeState::with(surface, ResizeState::commit) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if edges.left() {
|
||||
location.x = initial_rect.loc.x + initial_rect.size.w - geometry.size.w;
|
||||
}
|
||||
if edges.top() {
|
||||
location.y = initial_rect.loc.y + initial_rect.size.h - geometry.size.h;
|
||||
}
|
||||
if edges.left() || edges.top() {
|
||||
space.map_element(window, location, false);
|
||||
}
|
||||
pub fn handle_resize_commit(surface: &WlSurface) {
|
||||
// The compositor's visual rect owns the anchored edge. A delayed client
|
||||
// commit must not move the window or change its stacking order.
|
||||
ResizeState::with(surface, ResizeState::commit);
|
||||
}
|
||||
|
||||
fn constrained_size(
|
||||
|
||||
@@ -54,7 +54,7 @@ impl XdgActivationHandler for Ferese {
|
||||
tracing::error!(%error, ?focused, "failed to update workspace focus");
|
||||
return;
|
||||
}
|
||||
self.space.raise_element(&window, true);
|
||||
self.raise_window(&window, true);
|
||||
let keyboard = self.seat.get_keyboard().expect("seat has a keyboard");
|
||||
keyboard.set_focus(self, Some(surface), SERIAL_COUNTER.next_serial());
|
||||
self.space.elements().for_each(|window| {
|
||||
|
||||
@@ -12,7 +12,7 @@ use smithay::{
|
||||
Resource,
|
||||
protocol::{wl_seat, wl_surface::WlSurface},
|
||||
},
|
||||
utils::{Rectangle, Serial},
|
||||
utils::Serial,
|
||||
wayland::{
|
||||
compositor::with_states,
|
||||
shell::xdg::decoration::XdgDecorationHandler,
|
||||
@@ -136,7 +136,7 @@ impl XdgShellHandler for Ferese {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(initial_location) = self.space.element_location(&window) else {
|
||||
let Some(initial_rect) = self.visual_rect_for_window(&window) else {
|
||||
return;
|
||||
};
|
||||
if !self.is_floating_window(&window) {
|
||||
@@ -147,7 +147,8 @@ impl XdgShellHandler for Ferese {
|
||||
MoveSurfaceGrab {
|
||||
start_data,
|
||||
window,
|
||||
initial_location,
|
||||
initial_location: initial_rect.loc,
|
||||
initial_size: initial_rect.size,
|
||||
finished: false,
|
||||
},
|
||||
serial,
|
||||
@@ -183,13 +184,12 @@ impl XdgShellHandler for Ferese {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(location) = self.space.element_location(&window) else {
|
||||
let Some(rect) = self.visual_rect_for_window(&window) else {
|
||||
return;
|
||||
};
|
||||
if !self.is_floating_window(&window) {
|
||||
return;
|
||||
}
|
||||
let rect = Rectangle::new(location, window.geometry().size);
|
||||
pointer.set_grab(
|
||||
self,
|
||||
ResizeSurfaceGrab::new(start_data, window, ResizeEdge::from(edges), rect),
|
||||
@@ -314,7 +314,7 @@ fn set_decoration_mode(toplevel: &ToplevelSurface, mode: Mode) {
|
||||
}
|
||||
|
||||
pub fn handle_commit(popups: &mut PopupManager, space: &mut Space<Window>, surface: &WlSurface) {
|
||||
handle_resize_commit(space, surface);
|
||||
handle_resize_commit(surface);
|
||||
if let Some(window) = space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
|
||||
@@ -308,7 +308,7 @@ impl Ferese {
|
||||
{
|
||||
tracing::error!(%error, ?focused, "failed to update workspace focus");
|
||||
}
|
||||
self.space.raise_element(&window, true);
|
||||
self.raise_window(&window, true);
|
||||
let surface = window
|
||||
.toplevel()
|
||||
.expect("mapped window has a toplevel")
|
||||
|
||||
@@ -8,6 +8,7 @@ mod handlers;
|
||||
mod input;
|
||||
mod ipc;
|
||||
mod metrics;
|
||||
mod stacking;
|
||||
mod state;
|
||||
mod window_rules;
|
||||
mod winit;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
use ferese_layout::WindowId;
|
||||
|
||||
/// Persistent back-to-front order. Geometry updates never change this order.
|
||||
#[derive(Default)]
|
||||
pub(crate) struct WindowStack {
|
||||
order: Vec<WindowId>,
|
||||
}
|
||||
|
||||
impl WindowStack {
|
||||
pub fn insert(&mut self, id: WindowId) {
|
||||
if !self.order.contains(&id) {
|
||||
self.order.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: WindowId) {
|
||||
self.order.retain(|candidate| *candidate != id);
|
||||
}
|
||||
|
||||
pub fn raise(&mut self, id: WindowId) {
|
||||
self.remove(id);
|
||||
self.insert(id);
|
||||
}
|
||||
|
||||
pub fn rank(&self, id: WindowId) -> usize {
|
||||
self.order
|
||||
.iter()
|
||||
.position(|candidate| *candidate == id)
|
||||
.unwrap_or(usize::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn remapping_neighbours_does_not_change_order() {
|
||||
let mut stack = WindowStack::default();
|
||||
stack.insert(WindowId(1));
|
||||
stack.insert(WindowId(2));
|
||||
stack.raise(WindowId(1));
|
||||
stack.insert(WindowId(2));
|
||||
assert!(stack.rank(WindowId(1)) > stack.rank(WindowId(2)));
|
||||
stack.remove(WindowId(1));
|
||||
assert_eq!(stack.rank(WindowId(2)), 0);
|
||||
}
|
||||
}
|
||||
+88
-54
@@ -45,7 +45,7 @@ use smithay::{
|
||||
protocol::wl_surface::WlSurface,
|
||||
},
|
||||
},
|
||||
utils::{Logical, Point, Size},
|
||||
utils::{Logical, Point, Rectangle, Size},
|
||||
wayland::{
|
||||
alpha_modifier::AlphaModifierState,
|
||||
compositor::{CompositorClientState, CompositorState, with_states},
|
||||
@@ -118,7 +118,7 @@ pub struct Ferese {
|
||||
output_identity_ids: HashMap<String, OutputId>,
|
||||
pub window_ids: HashMap<Window, WindowId>,
|
||||
pub window_geometry: HashMap<WindowId, WindowGeometry>,
|
||||
pub(crate) window_decoration_progress: HashMap<WindowId, AnimatedValue>,
|
||||
window_stack: crate::stacking::WindowStack,
|
||||
pub(crate) window_borders: HashMap<WindowId, crate::winit::WindowBorderBuffers>,
|
||||
pub(crate) window_shadows: HashMap<WindowId, crate::winit::WindowShadowBuffers>,
|
||||
pub(crate) rounded_clip_programs: HashMap<ErasedContextId, crate::winit::RoundedClipPrograms>,
|
||||
@@ -429,7 +429,7 @@ impl Ferese {
|
||||
output_identity_ids: HashMap::new(),
|
||||
window_ids: HashMap::new(),
|
||||
window_geometry: HashMap::new(),
|
||||
window_decoration_progress: HashMap::new(),
|
||||
window_stack: crate::stacking::WindowStack::default(),
|
||||
window_borders: HashMap::new(),
|
||||
window_shadows: HashMap::new(),
|
||||
rounded_clip_programs: HashMap::new(),
|
||||
@@ -634,11 +634,49 @@ impl Ferese {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn raise_window(&mut self, window: &Window, activate: bool) {
|
||||
if let Some(id) = self.window_ids.get(window) {
|
||||
self.window_stack.raise(*id);
|
||||
}
|
||||
self.space.raise_element(window, activate);
|
||||
self.sync_window_stacking();
|
||||
}
|
||||
|
||||
pub(crate) fn sync_window_stacking(&mut self) {
|
||||
let mut windows = self.space.elements().cloned().collect::<Vec<_>>();
|
||||
windows.sort_by_key(|window| {
|
||||
let id = self.window_ids.get(window).copied();
|
||||
let priority = id
|
||||
.and_then(|id| self.window_geometry.get(&id))
|
||||
.is_some_and(|geometry| geometry.is_fullscreen() || geometry.is_zooming());
|
||||
(
|
||||
priority,
|
||||
id.map_or(usize::MAX, |id| self.window_stack.rank(id)),
|
||||
)
|
||||
});
|
||||
for window in windows {
|
||||
self.space.raise_element(&window, false);
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
pub(crate) fn visual_rect_for_window(
|
||||
&self,
|
||||
window: &Window,
|
||||
) -> Option<Rectangle<i32, Logical>> {
|
||||
let id = self.window_ids.get(window)?;
|
||||
let rect = self.window_geometry.get(id)?.visual.current;
|
||||
let size = ClientSize::from_rect(rect);
|
||||
Some(Rectangle::new(
|
||||
(rect.x.round() as i32, rect.y.round() as i32).into(),
|
||||
(size.width, size.height).into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn add_tiled_window(&mut self, window: Window) {
|
||||
let id = WindowId(self.next_window_id);
|
||||
self.next_window_id += 1;
|
||||
@@ -661,6 +699,7 @@ impl Ferese {
|
||||
}
|
||||
|
||||
self.window_ids.insert(window.clone(), id);
|
||||
self.window_stack.insert(id);
|
||||
if focus_new_window {
|
||||
self.focused_window = Some(id);
|
||||
}
|
||||
@@ -695,6 +734,7 @@ impl Ferese {
|
||||
}
|
||||
|
||||
self.window_ids.insert(window.clone(), id);
|
||||
self.window_stack.insert(id);
|
||||
self.space.map_element(window, (0, 0), false);
|
||||
self.relayout();
|
||||
}
|
||||
@@ -821,7 +861,7 @@ impl Ferese {
|
||||
|
||||
self.space.unmap_elem(window);
|
||||
self.window_geometry.remove(&id);
|
||||
self.window_decoration_progress.remove(&id);
|
||||
self.window_stack.remove(id);
|
||||
self.window_borders.remove(&id);
|
||||
self.window_shadows.remove(&id);
|
||||
self.closing_windows.remove(&id);
|
||||
@@ -918,8 +958,6 @@ impl Ferese {
|
||||
|
||||
let rect = if workspace_fullscreen == Some(*id) {
|
||||
fullscreen_bounds
|
||||
} else if workspace_fullscreen.is_some() {
|
||||
continue;
|
||||
} else {
|
||||
match self.workspaces.placement(*id) {
|
||||
Some(WindowPlacement::Tiled) => {
|
||||
@@ -973,30 +1011,9 @@ impl Ferese {
|
||||
let now = self.start_time.elapsed();
|
||||
|
||||
let mut scrolling_world_x = HashMap::new();
|
||||
// map_element also raises windows. Keep relayout's HashMap iteration
|
||||
// order from randomly changing the stack during overlapping animations.
|
||||
let stacking_order = self
|
||||
.space
|
||||
.elements()
|
||||
.enumerate()
|
||||
.filter_map(|(index, window)| self.window_ids.get(window).map(|id| (*id, index)))
|
||||
.collect::<HashMap<_, _>>();
|
||||
placements.sort_by_key(|(_, id, ..)| stacking_order.get(id).copied().unwrap_or(usize::MAX));
|
||||
let mut fullscreen_transitions = Vec::new();
|
||||
placements.sort_by_key(|(_, id, ..)| self.window_stack.rank(*id));
|
||||
|
||||
for (window, id, rect, is_fullscreen, is_floating, scrolling, couple_width) in placements {
|
||||
let decoration_target = if is_fullscreen { 0.0 } else { 1.0 };
|
||||
let decorations = self
|
||||
.window_decoration_progress
|
||||
.entry(id)
|
||||
.or_insert_with(|| AnimatedValue::new(decoration_target));
|
||||
if decorations.target != decoration_target {
|
||||
fullscreen_transitions.push(window.clone());
|
||||
}
|
||||
decorations.set_target(decoration_target);
|
||||
if !self.animations_enabled {
|
||||
decorations.snap();
|
||||
}
|
||||
// A viewport-coupled width must never override fullscreen/floating geometry.
|
||||
if scrolling.is_none() {
|
||||
self.viewport_coupled_widths.remove(&id);
|
||||
@@ -1007,9 +1024,13 @@ impl Ferese {
|
||||
.window_geometry
|
||||
.entry(id)
|
||||
.or_insert_with(|| WindowGeometry::new(rect, committed_size));
|
||||
let requested_size = geometry.set_logical_target(rect, now);
|
||||
let mut requested_size = geometry.set_presentation_target(rect, is_fullscreen, now);
|
||||
if !self.animations_enabled {
|
||||
geometry.advance(Duration::ZERO, self.spring_config, false);
|
||||
requested_size = geometry.presentation_size_request(now).or(requested_size);
|
||||
}
|
||||
if geometry.is_zooming() {
|
||||
self.viewport_coupled_widths.remove(&id);
|
||||
}
|
||||
if let Some((workspace, world_x, viewport_x)) = scrolling {
|
||||
let restored_world_x = restored_scrolling_world_x(
|
||||
@@ -1027,15 +1048,17 @@ impl Ferese {
|
||||
if !self.animations_enabled {
|
||||
animated_world_x.snap();
|
||||
}
|
||||
geometry.visual.current.x = animated_world_x.current - viewport_x;
|
||||
geometry.visual.velocity.x = 0.0;
|
||||
if !geometry.is_zooming() {
|
||||
geometry.visual.current.x = animated_world_x.current - viewport_x;
|
||||
geometry.visual.velocity.x = animated_world_x.velocity;
|
||||
}
|
||||
scrolling_world_x.insert(id, (workspace, animated_world_x));
|
||||
|
||||
let coupled = couple_width
|
||||
|| self
|
||||
.viewport_coupled_widths
|
||||
.get(&id)
|
||||
.is_some_and(|(previous_workspace, _)| *previous_workspace == workspace);
|
||||
let coupled = !geometry.is_zooming()
|
||||
&& (couple_width
|
||||
|| self.viewport_coupled_widths.get(&id).is_some_and(
|
||||
|(previous_workspace, _)| *previous_workspace == workspace,
|
||||
));
|
||||
if coupled {
|
||||
let width = self.viewport_coupled_widths.entry(id).or_insert_with(|| {
|
||||
(workspace, AnimatedValue::new(geometry.visual.current.width))
|
||||
@@ -1099,11 +1122,7 @@ impl Ferese {
|
||||
}
|
||||
}
|
||||
self.scrolling_world_x = scrolling_world_x;
|
||||
// Neighbours are remapped on fullscreen exit; the shrinking window must
|
||||
// remain above them. Subsequent animation ticks preserve this ordering.
|
||||
for window in fullscreen_transitions {
|
||||
self.space.raise_element(&window, false);
|
||||
}
|
||||
self.sync_window_stacking();
|
||||
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
@@ -1175,16 +1194,10 @@ impl Ferese {
|
||||
|
||||
let mut settled_coupled_widths = Vec::new();
|
||||
for (window, id) in windows {
|
||||
if let Some(decorations) = self.window_decoration_progress.get_mut(&id) {
|
||||
if self.animations_enabled {
|
||||
active_animation |= decorations.advance(delta, self.spring_config);
|
||||
} else {
|
||||
decorations.snap();
|
||||
}
|
||||
}
|
||||
let Some(geometry) = self.window_geometry.get_mut(&id) else {
|
||||
continue;
|
||||
};
|
||||
let zooming = geometry.is_zooming();
|
||||
|
||||
let coupled_target = self
|
||||
.viewport_coupled_widths
|
||||
@@ -1202,13 +1215,18 @@ impl Ferese {
|
||||
if let Some((workspace, world_x)) = self.scrolling_world_x.get_mut(&id)
|
||||
&& let Some(viewport) = self.viewport_animations.get(workspace)
|
||||
{
|
||||
if self.animations_enabled {
|
||||
if zooming {
|
||||
world_x.current = geometry.visual.current.x + viewport.current;
|
||||
world_x.velocity = geometry.visual.velocity.x + viewport.velocity;
|
||||
} else if self.animations_enabled {
|
||||
active_animation |= world_x.advance(delta, self.spring_config);
|
||||
} else {
|
||||
world_x.snap();
|
||||
}
|
||||
geometry.visual.current.x = world_x.current - viewport.current;
|
||||
geometry.visual.velocity.x = 0.0;
|
||||
if !zooming {
|
||||
geometry.visual.current.x = world_x.current - viewport.current;
|
||||
geometry.visual.velocity.x = world_x.velocity - viewport.velocity;
|
||||
}
|
||||
}
|
||||
if let Some((_, width)) = self.viewport_coupled_widths.get_mut(&id) {
|
||||
let width_active = if self.animations_enabled {
|
||||
@@ -1233,6 +1251,14 @@ impl Ferese {
|
||||
"client did not commit the final configured size within 500 ms"
|
||||
);
|
||||
}
|
||||
if let Some(size) = geometry.presentation_size_request(self.start_time.elapsed())
|
||||
&& let Some(toplevel) = window.toplevel()
|
||||
{
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.size = Some((size.width, size.height).into());
|
||||
});
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
let visual = geometry.visual.current;
|
||||
self.space.map_element(
|
||||
window,
|
||||
@@ -1243,6 +1269,7 @@ impl Ferese {
|
||||
for id in settled_coupled_widths {
|
||||
self.viewport_coupled_widths.remove(&id);
|
||||
}
|
||||
self.sync_window_stacking();
|
||||
|
||||
active_animation
|
||||
}
|
||||
@@ -1302,7 +1329,7 @@ impl Ferese {
|
||||
};
|
||||
|
||||
self.focused_window = Some(next);
|
||||
self.space.raise_element(&window, true);
|
||||
self.raise_window(&window, true);
|
||||
self.seat
|
||||
.get_keyboard()
|
||||
.expect("seat has a keyboard")
|
||||
@@ -1585,11 +1612,18 @@ impl Ferese {
|
||||
.window_geometry
|
||||
.entry(id)
|
||||
.or_insert_with(|| WindowGeometry::new(rect, client_size(window)));
|
||||
geometry.set_logical_target(rect, self.start_time.elapsed());
|
||||
geometry.visual.snap();
|
||||
if let Some(size) = geometry.follow_pointer(rect, self.start_time.elapsed())
|
||||
&& let Some(toplevel) = window.toplevel()
|
||||
{
|
||||
toplevel.with_pending_state(|state| {
|
||||
state.size = Some((size.width, size.height).into());
|
||||
});
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
self.scrolling_world_x.remove(&id);
|
||||
self.viewport_coupled_widths.remove(&id);
|
||||
self.space.map_element(window.clone(), location, false);
|
||||
self.sync_window_stacking();
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
|
||||
|
||||
+18
-4
@@ -264,6 +264,7 @@ struct RoundedSurfaceRenderElement {
|
||||
program: GlesTexProgram,
|
||||
clip_rect: [f32; 4],
|
||||
radius: f32,
|
||||
clip_changed: bool,
|
||||
}
|
||||
|
||||
impl Element for RoundedSurfaceRenderElement {
|
||||
@@ -292,11 +293,18 @@ impl Element for RoundedSurfaceRenderElement {
|
||||
scale: RenderScale<f64>,
|
||||
commit: Option<CommitCounter>,
|
||||
) -> DamageSet<i32, Physical> {
|
||||
if self.clip_changed {
|
||||
return DamageSet::from_slice(&[Rectangle::from_size(self.inner.geometry(scale).size)]);
|
||||
}
|
||||
self.inner.damage_since(scale, commit)
|
||||
}
|
||||
|
||||
fn opaque_regions(&self, _scale: RenderScale<f64>) -> OpaqueRegions<i32, Physical> {
|
||||
OpaqueRegions::default()
|
||||
fn opaque_regions(&self, scale: RenderScale<f64>) -> OpaqueRegions<i32, Physical> {
|
||||
if self.radius == 0.0 {
|
||||
self.inner.opaque_regions(scale)
|
||||
} else {
|
||||
OpaqueRegions::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn alpha(&self) -> f32 {
|
||||
@@ -575,9 +583,9 @@ fn output_elements(
|
||||
let (close_scale, close_alpha) = state.closing_visual(id);
|
||||
let visual = scaled_visual_rect(visual, close_scale);
|
||||
let decoration_progress = state
|
||||
.window_decoration_progress
|
||||
.window_geometry
|
||||
.get(&id)
|
||||
.map_or(1.0, |progress| progress.current.clamp(0.0, 1.0));
|
||||
.map_or(1.0, |geometry| geometry.decorations.clamp(0.0, 1.0));
|
||||
|
||||
Some((window.clone(), id, visual, decoration_progress, close_alpha))
|
||||
})
|
||||
@@ -641,6 +649,10 @@ fn output_elements(
|
||||
scale,
|
||||
window_radius,
|
||||
close_alpha,
|
||||
state
|
||||
.window_geometry
|
||||
.get(&id)
|
||||
.is_some_and(|geometry| geometry.presentation_changed),
|
||||
output,
|
||||
programs.texture.clone(),
|
||||
));
|
||||
@@ -905,6 +917,7 @@ fn rounded_window_elements(
|
||||
scale: f64,
|
||||
requested_radius: f64,
|
||||
alpha: f32,
|
||||
clip_changed: bool,
|
||||
output: &Output,
|
||||
program: GlesTexProgram,
|
||||
) -> Vec<AnimatedWindowRenderElement> {
|
||||
@@ -966,6 +979,7 @@ fn rounded_window_elements(
|
||||
program: program.clone(),
|
||||
clip_rect: clip,
|
||||
radius,
|
||||
clip_changed,
|
||||
}
|
||||
.into()
|
||||
}),
|
||||
|
||||
Reference in new issue
Block a user