element: Refactor remaining libcosmic elements for blur

This commit is contained in:
Victoria Brekenfeld 2026-04-21 18:19:01 +02:00 committed by Victoria Brekenfeld
parent 6c76fdaa79
commit db06770a6b
9 changed files with 444 additions and 142 deletions

View file

@ -1,10 +1,11 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::{ use crate::{
backend::render::element::AsGlowRenderer,
config::Config, config::Config,
fl, fl,
shell::grabs::ResizeEdge, shell::grabs::ResizeEdge,
utils::iced::{IcedElement, Program}, utils::iced::{IcedElement, IcedRenderElement, Program},
}; };
use calloop::LoopHandle; use calloop::LoopHandle;
@ -19,48 +20,233 @@ use cosmic::{
widget::{icon::from_name, text}, widget::{icon::from_name, text},
}; };
use cosmic_settings_config::shortcuts::action::{Action, ResizeDirection}; use cosmic_settings_config::shortcuts::action::{Action, ResizeDirection};
use smithay::utils::Size; use smithay::{
backend::renderer::ImportMem,
desktop::space::SpaceElement,
output::Output,
utils::{Logical, Physical, Point, Rectangle, Scale, Size},
};
pub type ResizeIndicator = IcedElement<ResizeIndicatorInternal>; #[derive(Debug, Clone)]
pub struct ResizeIndicator {
edges: ResizeEdge,
direction: Arc<Mutex<ResizeDirection>>,
size: Size<i32, Logical>,
pub fn resize_indicator( center_elem: IcedElement<ResizeIndicatorInternal>,
direction: ResizeDirection, left_elem: IcedElement<ResizeIndicatorArrow>,
config: &Config, top_elem: IcedElement<ResizeIndicatorArrow>,
evlh: LoopHandle<'static, crate::state::State>, right_elem: IcedElement<ResizeIndicatorArrow>,
theme: cosmic::Theme, down_elem: IcedElement<ResizeIndicatorArrow>,
) -> ResizeIndicator { }
ResizeIndicator::new(
ResizeIndicatorInternal { const ARROW_SIZE: i32 = 36;
edges: Mutex::new(ResizeEdge::all()),
direction, impl ResizeIndicator {
shortcut1: config pub fn new(
.shortcuts direction: ResizeDirection,
.iter() config: &Config,
.find_map(|(pattern, action)| { evlh: LoopHandle<'static, crate::state::State>,
(*action == Action::Resizing(ResizeDirection::Outwards)).then_some(pattern) mut theme: cosmic::Theme,
}) ) -> ResizeIndicator {
.map(|pattern| format!("{}: ", pattern.to_string())) theme.transparent = theme.cosmic().frosted_system_interface;
.unwrap_or_else(|| crate::fl!("unknown-keybinding")), let direction = Arc::new(Mutex::new(direction));
shortcut2: config
.shortcuts ResizeIndicator {
.iter() edges: ResizeEdge::all(),
.find_map(|(pattern, action)| { direction: direction.clone(),
(*action == Action::Resizing(ResizeDirection::Inwards)).then_some(pattern) size: Size::default(),
}) center_elem: IcedElement::new(
.map(|pattern| format!("{}: ", pattern.to_string())) ResizeIndicatorInternal {
.unwrap_or_else(|| crate::fl!("unknown-keybinding")), shortcut1: config
}, .shortcuts
Size::from((1, 1)), .iter()
evlh, .find_map(|(pattern, action)| {
theme, (*action == Action::Resizing(ResizeDirection::Outwards))
) .then_some(pattern)
})
.map(|pattern| format!("{}: ", pattern.to_string()))
.unwrap_or_else(|| crate::fl!("unknown-keybinding")),
shortcut2: config
.shortcuts
.iter()
.find_map(|(pattern, action)| {
(*action == Action::Resizing(ResizeDirection::Inwards))
.then_some(pattern)
})
.map(|pattern| format!("{}: ", pattern.to_string()))
.unwrap_or_else(|| crate::fl!("unknown-keybinding")),
},
Size::from((1, 1)),
evlh.clone(),
theme.clone(),
),
left_elem: IcedElement::new(
ResizeIndicatorArrow {
direction: direction.clone(),
icon_outwards: "go-previous-symbolic",
icon_inwards: "go-next-symbolic",
},
Size::from((ARROW_SIZE, ARROW_SIZE)),
evlh.clone(),
theme.clone(),
),
top_elem: IcedElement::new(
ResizeIndicatorArrow {
direction: direction.clone(),
icon_outwards: "go-up-symbolic",
icon_inwards: "go-down-symbolic",
},
Size::from((ARROW_SIZE, ARROW_SIZE)),
evlh.clone(),
theme.clone(),
),
right_elem: IcedElement::new(
ResizeIndicatorArrow {
direction: direction.clone(),
icon_outwards: "go-next-symbolic",
icon_inwards: "go-previous-symbolic",
},
Size::from((ARROW_SIZE, ARROW_SIZE)),
evlh.clone(),
theme.clone(),
),
down_elem: IcedElement::new(
ResizeIndicatorArrow {
direction,
icon_outwards: "go-down-symbolic",
icon_inwards: "go-up-symbolic",
},
Size::from((ARROW_SIZE, ARROW_SIZE)),
evlh.clone(),
theme.clone(),
),
}
}
pub fn resize(&mut self, size: Size<i32, Logical>) {
let minimum = self.center_elem.minimum_size();
let new_size = Size::<i32, Logical>::new(size.w.min(minimum.w), size.h.min(minimum.h));
self.center_elem.resize(new_size);
self.size = size;
}
pub fn push_render_elements<R>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
scale: Scale<f64>,
alpha: f32,
push_above: &mut dyn FnMut(IcedRenderElement<R>),
mut push_below: Option<&mut dyn FnMut(IcedRenderElement<R>)>,
) where
R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
let elem_size = self.center_elem.current_size();
let center_location = Point::new(
self.size.w.saturating_sub(elem_size.w) / 2,
self.size.h.saturating_sub(elem_size.h) / 2,
);
let left_location = Point::new(0, self.size.h.saturating_sub(ARROW_SIZE) / 2);
let top_location = Point::new(self.size.w.saturating_sub(ARROW_SIZE) / 2, 0);
let right_location = Point::new(
self.size.w.saturating_sub(ARROW_SIZE),
self.size.h.saturating_sub(ARROW_SIZE) / 2,
);
let down_location = Point::new(
self.size.w.saturating_sub(ARROW_SIZE) / 2,
self.size.h.saturating_sub(ARROW_SIZE),
);
let radii = self
.center_elem
.with_theme(|theme| theme.cosmic().radius_s())
.map(|x| x.round() as u8);
self.center_elem.push_render_elements(
renderer,
location + center_location.to_physical_precise_round(scale),
scale,
alpha,
radii,
push_above,
if let Some(push_below) = push_below.as_mut() {
Some(&mut **push_below)
} else {
None
},
);
let mut render = move |elem: &IcedElement<ResizeIndicatorArrow>,
loc: Point<i32, Logical>| {
elem.push_render_elements(
renderer,
location + loc.to_physical_precise_round(scale),
scale,
alpha,
radii,
push_above,
if let Some(push_below) = push_below.as_mut() {
Some(&mut **push_below)
} else {
None
},
);
};
if self.edges.contains(ResizeEdge::LEFT) {
render(&self.left_elem, left_location);
}
if self.edges.contains(ResizeEdge::TOP) {
render(&self.top_elem, top_location);
}
if self.edges.contains(ResizeEdge::RIGHT) {
render(&self.right_elem, right_location);
}
if self.edges.contains(ResizeEdge::BOTTOM) {
render(&self.down_elem, down_location);
}
}
pub fn set_edges(&mut self, edges: ResizeEdge) {
self.edges = edges;
}
pub fn set_direction(&self, direction: ResizeDirection) {
let mut dir_ref = self.direction.lock().unwrap();
if *dir_ref != direction {
*dir_ref = direction;
self.left_elem.force_redraw();
self.top_elem.force_redraw();
self.right_elem.force_redraw();
self.down_elem.force_redraw();
}
}
pub fn output_enter(&self, output: &Output) {
self.center_elem
.output_enter(output, Rectangle::default() /*unused*/);
self.left_elem
.output_enter(output, Rectangle::default() /*unused*/);
self.top_elem
.output_enter(output, Rectangle::default() /*unused*/);
self.right_elem
.output_enter(output, Rectangle::default() /*unused*/);
self.down_elem
.output_enter(output, Rectangle::default() /*unused*/);
}
pub fn output_leave(&self, output: &Output) {
self.center_elem.output_leave(output);
self.left_elem.output_leave(output);
self.top_elem.output_leave(output);
self.right_elem.output_leave(output);
self.down_elem.output_leave(output);
}
} }
pub struct ResizeIndicatorInternal { pub struct ResizeIndicatorInternal {
pub edges: Mutex<ResizeEdge>, shortcut1: String,
pub direction: ResizeDirection, shortcut2: String,
pub shortcut1: String,
pub shortcut2: String,
} }
impl Program for ResizeIndicatorInternal { impl Program for ResizeIndicatorInternal {
@ -94,7 +280,7 @@ impl Program for ResizeIndicatorInternal {
text_color: Some(Color::from(theme.cosmic().accent.on)), text_color: Some(Color::from(theme.cosmic().accent.on)),
background: Some(Background::Color(background.into())), background: Some(Background::Color(background.into())),
border: Border { border: Border {
radius: 18.0.into(), radius: theme.cosmic().radius_s().into(),
width: 0.0, width: 0.0,
color: Color::TRANSPARENT, color: Color::TRANSPARENT,
}, },

View file

@ -1,6 +1,7 @@
use crate::{ use crate::{
backend::render::element::AsGlowRenderer,
fl, fl,
utils::iced::{IcedElement, Program}, utils::iced::{IcedElement, IcedRenderElement, Program},
}; };
use calloop::LoopHandle; use calloop::LoopHandle;
@ -14,16 +15,72 @@ use cosmic::{
theme, theme,
widget::{icon::from_name, space, text}, widget::{icon::from_name, space, text},
}; };
use smithay::utils::{Logical, Size}; use smithay::{
backend::renderer::ImportMem,
desktop::space::SpaceElement,
output::Output,
utils::{Logical, Physical, Point, Rectangle, Scale, Size},
};
pub type StackHover = IcedElement<StackHoverInternal>; #[derive(Debug)]
pub struct StackHover {
location: Point<i32, Logical>,
elem: IcedElement<StackHoverInternal>,
}
pub fn stack_hover( impl StackHover {
evlh: LoopHandle<'static, crate::state::State>, pub fn new(
size: Size<i32, Logical>, evlh: LoopHandle<'static, crate::state::State>,
theme: cosmic::Theme, size: Size<i32, Logical>,
) -> StackHover { mut theme: cosmic::Theme,
StackHover::new(StackHoverInternal, size, evlh, theme) ) -> StackHover {
theme.transparent = theme.cosmic().frosted_system_interface;
let elem = IcedElement::new(StackHoverInternal, size, evlh, theme);
let minimum = elem.minimum_size();
let new_size = Size::<i32, Logical>::new(size.w.min(minimum.w), size.h.min(minimum.h));
let location = Point::new(
size.w.saturating_sub(new_size.w) / 2,
size.h.saturating_sub(new_size.h) / 2,
);
elem.resize(new_size);
StackHover { location, elem }
}
pub fn push_render_elements<R>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
scale: Scale<f64>,
alpha: f32,
push_above: &mut dyn FnMut(IcedRenderElement<R>),
push_below: Option<&mut dyn FnMut(IcedRenderElement<R>)>,
) where
R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
self.elem.push_render_elements(
renderer,
location + self.location.to_physical_precise_round(scale),
scale,
alpha,
self.elem
.with_theme(|theme| theme.cosmic().radius_s())
.map(|x| x.round() as u8),
push_above,
push_below,
);
}
pub fn output_enter(&self, output: &Output) {
self.elem
.output_enter(output, Rectangle::default() /*unused*/);
}
pub fn output_leave(&self, output: &Output) {
self.elem.output_leave(output);
}
} }
pub struct StackHoverInternal; pub struct StackHoverInternal;
@ -71,9 +128,6 @@ impl Program for StackHoverInternal {
})) }))
.width(Length::Shrink) .width(Length::Shrink)
.height(Length::Shrink) .height(Length::Shrink)
.apply(container)
.center_x(Length::Fill)
.center_y(Length::Fill)
.into() .into()
} }
} }

View file

@ -1,6 +1,7 @@
use crate::{ use crate::{
backend::render::element::AsGlowRenderer,
fl, fl,
utils::iced::{IcedElement, Program}, utils::iced::{IcedElement, IcedRenderElement, Program},
}; };
use calloop::LoopHandle; use calloop::LoopHandle;
@ -13,15 +14,75 @@ use cosmic::{
theme, theme,
widget::{icon::from_name, text}, widget::{icon::from_name, text},
}; };
use smithay::utils::Size; use smithay::{
backend::renderer::ImportMem,
desktop::space::SpaceElement,
output::Output,
utils::{Logical, Physical, Point, Rectangle, Scale, Size},
};
pub type SwapIndicator = IcedElement<SwapIndicatorInternal>; #[derive(Debug, Clone)]
pub struct SwapIndicator {
location: Point<i32, Logical>,
elem: IcedElement<SwapIndicatorInternal>,
}
pub fn swap_indicator( impl SwapIndicator {
evlh: LoopHandle<'static, crate::state::State>, pub fn new(
theme: cosmic::Theme, evlh: LoopHandle<'static, crate::state::State>,
) -> SwapIndicator { mut theme: cosmic::Theme,
SwapIndicator::new(SwapIndicatorInternal, Size::from((1, 1)), evlh, theme) ) -> SwapIndicator {
theme.transparent = theme.cosmic().frosted_system_interface;
SwapIndicator {
location: Point::default(),
elem: IcedElement::new(SwapIndicatorInternal, Size::from((1, 1)), evlh, theme),
}
}
pub fn resize(&mut self, size: Size<i32, Logical>) {
let minimum = self.elem.minimum_size();
let new_size = Size::<i32, Logical>::new(size.w.min(minimum.w), size.h.min(minimum.h));
let location = Point::new(
size.w.saturating_sub(new_size.w) / 2,
size.h.saturating_sub(new_size.h) / 2,
);
self.elem.resize(new_size);
self.location = location;
}
pub fn push_render_elements<R>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
scale: Scale<f64>,
alpha: f32,
push_above: &mut dyn FnMut(IcedRenderElement<R>),
push_below: Option<&mut dyn FnMut(IcedRenderElement<R>)>,
) where
R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
self.elem.push_render_elements(
renderer,
location + self.location.to_physical_precise_round(scale),
scale,
alpha,
self.elem
.with_theme(|theme| theme.cosmic().radius_s())
.map(|x| x.round() as u8),
push_above,
push_below,
);
}
pub fn output_enter(&self, output: &Output) {
self.elem
.output_enter(output, Rectangle::default() /*unused*/);
}
pub fn output_leave(&self, output: &Output) {
self.elem.output_leave(output);
}
} }
pub struct SwapIndicatorInternal; pub struct SwapIndicatorInternal;
@ -69,9 +130,6 @@ impl Program for SwapIndicatorInternal {
})) }))
.width(Length::Shrink) .width(Length::Shrink)
.height(Length::Shrink) .height(Length::Shrink)
.apply(container)
.center_x(Length::Fill)
.center_y(Length::Fill)
.into() .into()
} }
} }

View file

@ -20,7 +20,7 @@ use cosmic::{
use smithay::{ use smithay::{
backend::{ backend::{
input::{ButtonState, TouchSlot}, input::{ButtonState, TouchSlot},
renderer::{ImportMem, Renderer, element::memory::MemoryRenderBufferRenderElement}, renderer::ImportMem,
}, },
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{ input::{
@ -42,10 +42,11 @@ use smithay::{
}; };
use crate::{ use crate::{
backend::render::element::AsGlowRenderer,
shell::{SeatExt, focus::target::PointerFocusTarget}, shell::{SeatExt, focus::target::PointerFocusTarget},
state::State, state::State,
utils::{ utils::{
iced::{IcedElement, Program}, iced::{IcedElement, IcedRenderElement, Program},
prelude::*, prelude::*,
}, },
}; };
@ -68,9 +69,9 @@ impl MenuGrabState {
&self, &self,
renderer: &mut R, renderer: &mut R,
output: &Output, output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>), push: &mut dyn FnMut(IcedRenderElement<R>),
) where ) where
R: Renderer + ImportMem, R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
let scale = output.current_scale().fractional_scale(); let scale = output.current_scale().fractional_scale();
@ -83,7 +84,11 @@ impl MenuGrabState {
.to_physical_precise_round(scale), .to_physical_precise_round(scale),
scale.into(), scale.into(),
1.0, 1.0,
elem.iced
.with_theme(|theme| theme.cosmic().radius_s())
.map(|x| x.round() as u8),
push, push,
None,
) )
} }
} }
@ -274,11 +279,13 @@ impl Program for ContextMenu {
let mut elements = grab_state.elements.lock().unwrap(); let mut elements = grab_state.elements.lock().unwrap();
let position = elements.last().unwrap().position; let position = elements.last().unwrap().position;
let mut theme = state.common.theme.clone();
theme.transparent = theme.cosmic().frosted_system_interface;
let element = IcedElement::new( let element = IcedElement::new(
ContextMenu::new(items), ContextMenu::new(items),
Size::default(), Size::default(),
state.common.event_loop_handle.clone(), state.common.event_loop_handle.clone(),
state.common.theme.clone(), theme,
); );
let min_size = element.minimum_size(); let min_size = element.minimum_size();
@ -474,7 +481,7 @@ impl Program for ContextMenu {
.padding(1) .padding(1)
.class(theme::Container::custom(|theme| { .class(theme::Container::custom(|theme| {
let cosmic = theme.cosmic(); let cosmic = theme.cosmic();
let component = &cosmic.background(false).component; let component = &cosmic.background(theme.cosmic().frosted_windows).component;
iced_widget::container::Style { iced_widget::container::Style {
snap: true, snap: true,
icon_color: Some(cosmic.accent.base.into()), icon_color: Some(cosmic.accent.base.into()),

View file

@ -6,10 +6,7 @@ use crate::{
}, },
shell::{ shell::{
CosmicMapped, CosmicSurface, Direction, ManagedLayer, CosmicMapped, CosmicSurface, Direction, ManagedLayer,
element::{ element::{CosmicMappedRenderElement, stack_hover::StackHover},
CosmicMappedRenderElement,
stack_hover::{StackHover, stack_hover},
},
focus::target::{KeyboardFocusTarget, PointerFocusTarget}, focus::target::{KeyboardFocusTarget, PointerFocusTarget},
layout::floating::TiledCorners, layout::floating::TiledCorners,
}, },
@ -25,7 +22,7 @@ use smithay::{
drm::DrmNode, drm::DrmNode,
input::ButtonState, input::ButtonState,
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem,
element::{RenderElement, utils::RescaleRenderElement}, element::{RenderElement, utils::RescaleRenderElement},
}, },
}, },
@ -78,7 +75,7 @@ impl MoveGrabState {
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
push: &mut dyn FnMut(CosmicMappedRenderElement<R>), push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where ) where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: AsGlowRenderer + ImportAll + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
{ {
@ -122,6 +119,7 @@ impl MoveGrabState {
output_scale, output_scale,
1.0, 1.0,
&mut |elem| push(elem.into()), &mut |elem| push(elem.into()),
None,
); );
} }
@ -441,7 +439,7 @@ impl MoveGrab {
if let Some(indicator) = if let Some(indicator) =
grab_state.stacking_indicator.as_ref().map(|x| &x.0) grab_state.stacking_indicator.as_ref().map(|x| &x.0)
{ {
indicator.output_enter(output, overlap); indicator.output_enter(output);
} }
} }
} else if self.window_outputs.remove(output) { } else if self.window_outputs.remove(output) {
@ -455,16 +453,14 @@ impl MoveGrab {
let indicator_location = shell.stacking_indicator(&current_output, self.previous); let indicator_location = shell.stacking_indicator(&current_output, self.previous);
if indicator_location.is_some() != grab_state.stacking_indicator.is_some() { if indicator_location.is_some() != grab_state.stacking_indicator.is_some() {
grab_state.stacking_indicator = indicator_location.map(|geo| { grab_state.stacking_indicator = indicator_location.map(|geo| {
let element = stack_hover( let size = geo.size.as_logical();
let element = StackHover::new(
state.common.event_loop_handle.clone(), state.common.event_loop_handle.clone(),
geo.size.as_logical(), size,
state.common.theme.clone(), state.common.theme.clone(),
); );
for output in &self.window_outputs { for output in &self.window_outputs {
element.output_enter( element.output_enter(output);
output,
Rectangle::from_size(output.geometry().size.as_logical()),
);
} }
(element, geo.loc.as_logical()) (element, geo.loc.as_logical())
}); });

View file

@ -1525,6 +1525,27 @@ impl FloatingLayout {
if focused == Some(elem) && !elem.is_maximized(false) { if focused == Some(elem) && !elem.is_maximized(false) {
let active_window_hint = crate::theme::active_window_hint(theme); let active_window_hint = crate::theme::active_window_hint(theme);
let radius = elem.corner_radius(geometry.size.as_logical(), indicator_thickness); let radius = elem.corner_radius(geometry.size.as_logical(), indicator_thickness);
if let Some((mode, resize)) = resize_indicator.as_mut() {
let mut resize_geometry = geometry;
resize_geometry.loc -= (18, 18).into();
resize_geometry.size += (36, 36).into();
resize.resize(resize_geometry.size.as_logical());
resize.output_enter(output);
resize.push_render_elements(
renderer,
resize_geometry
.loc
.as_logical()
.to_physical_precise_round(output_scale),
output_scale.into(),
alpha * mode.alpha().unwrap_or(1.0),
&mut |elem| push(CosmicMappedRenderElement::Window(elem.into())),
None,
);
}
if indicator_thickness > 0 { if indicator_thickness > 0 {
let element = IndicatorShader::focus_element( let element = IndicatorShader::focus_element(
renderer, renderer,
@ -1542,25 +1563,6 @@ impl FloatingLayout {
); );
push(element.into()); push(element.into());
} }
if let Some((mode, resize)) = resize_indicator.as_mut() {
let mut resize_geometry = geometry;
resize_geometry.loc -= (18, 18).into();
resize_geometry.size += (36, 36).into();
resize.resize(resize_geometry.size.as_logical());
resize.output_enter(output, Rectangle::default() /* unused */);
resize.push_render_elements(
renderer,
resize_geometry
.loc
.as_logical()
.to_physical_precise_round(output_scale),
output_scale.into(),
alpha * mode.alpha().unwrap_or(1.0),
&mut |elem| push(CosmicMappedRenderElement::Window(elem.into())),
);
}
} }
let maybe_map = if let Some(anim) = self.animations.get(elem) { let maybe_map = if let Some(anim) = self.animations.get(elem) {

View file

@ -5330,13 +5330,12 @@ fn render_new_tree_windows<R>(
let mut group_backdrop = None; let mut group_backdrop = None;
let mut indicators = SmallVec::<[CosmicMappedRenderElement<R>; 2]>::new_const(); let mut indicators = SmallVec::<[CosmicMappedRenderElement<R>; 2]>::new_const();
let mut resize_element = None; let mut resize_elements = SmallVec::<[CosmicMappedRenderElement<R>; 10]>::new_const();
let mut swap_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const(); let mut swap_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
let output_geo = output.geometry();
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
let (swap_indicator, swap_tree) = overview.1.unzip(); let (mut swap_indicator, swap_tree) = overview.1.unzip();
let swap_desc = swap_desc.filter(|_| is_active_output); let swap_desc = swap_desc.filter(|_| is_active_output);
let swap_tree = swap_tree.flatten().filter(|_| is_active_output); let swap_tree = swap_tree.flatten().filter(|_| is_active_output);
let window_hint = crate::theme::active_window_hint(theme); let window_hint = crate::theme::active_window_hint(theme);
@ -5540,16 +5539,18 @@ fn render_new_tree_windows<R>(
.unwrap_or(false) .unwrap_or(false)
}) })
.unwrap_or(false)) .unwrap_or(false))
&& let Some(swap) = swap_indicator.as_ref() && let Some(swap) = swap_indicator.as_mut()
{ {
swap.resize(geo.size.as_logical()); let size = geo.size.as_logical();
swap.output_enter(output, output_geo.as_logical()); swap.resize(size);
swap.output_enter(output);
swap.push_render_elements( swap.push_render_elements(
renderer, renderer,
geo.loc.as_logical().to_physical_precise_round(output_scale), geo.loc.as_logical().to_physical_precise_round(output_scale),
output_scale.into(), output_scale.into(),
alpha * overview.0.alpha().unwrap_or(1.0), alpha * overview.0.alpha().unwrap_or(1.0),
&mut |elem| swap_elements.push(elem.into()), &mut |elem| swap_elements.push(elem.into()),
None,
); );
} }
} }
@ -5560,29 +5561,20 @@ fn render_new_tree_windows<R>(
geo.size += (36, 36).into(); geo.size += (36, 36).into();
resize.resize(geo.size.as_logical()); resize.resize(geo.size.as_logical());
resize.output_enter(output, output_geo.as_logical()); resize.output_enter(output);
let possible_edges = let possible_edges =
TilingLayout::possible_resizes(target_tree, node_id.clone()); TilingLayout::possible_resizes(target_tree, node_id.clone());
if !possible_edges.is_empty() { if !possible_edges.is_empty() {
if resize.with_program(|internal| { resize.set_edges(possible_edges);
let mut edges = internal.edges.lock().unwrap();
if *edges != possible_edges {
*edges = possible_edges;
true
} else {
false
}
}) {
resize.force_update();
}
resize.push_render_elements( resize.push_render_elements(
renderer, renderer,
geo.loc.as_logical().to_physical_precise_round(output_scale), geo.loc.as_logical().to_physical_precise_round(output_scale),
output_scale.into(), output_scale.into(),
alpha * mode.alpha().unwrap_or(1.0), alpha * mode.alpha().unwrap_or(1.0),
&mut |elem| { &mut |elem| {
resize_element = Some(elem.into()); resize_elements.push(elem.into());
}, },
None,
); );
} }
} }
@ -5743,7 +5735,7 @@ fn render_new_tree_windows<R>(
}, },
); );
for elem in resize_element for elem in resize_elements
.into_iter() .into_iter()
.chain(swap_elements) .chain(swap_elements)
.chain(indicators) .chain(indicators)

View file

@ -102,9 +102,8 @@ use self::zoom::{OutputZoomState, ZoomState};
use self::{ use self::{
element::{ element::{
CosmicWindow, MaximizedState, CosmicWindow, MaximizedState, resize_indicator::ResizeIndicator,
resize_indicator::{ResizeIndicator, resize_indicator}, swap_indicator::SwapIndicator,
swap_indicator::{SwapIndicator, swap_indicator},
}, },
focus::target::{KeyboardFocusTarget, PointerFocusTarget}, focus::target::{KeyboardFocusTarget, PointerFocusTarget},
grabs::{ grabs::{
@ -2291,7 +2290,7 @@ impl Shell {
OverviewMode::Started(_, _) | OverviewMode::Active(_) OverviewMode::Started(_, _) | OverviewMode::Active(_)
) { ) {
if matches!(trigger, Trigger::KeyboardSwap(_, _)) { if matches!(trigger, Trigger::KeyboardSwap(_, _)) {
self.swap_indicator = Some(swap_indicator(evlh, self.theme.clone())); self.swap_indicator = Some(SwapIndicator::new(evlh, self.theme.clone()));
} }
self.overview_mode = OverviewMode::Started(trigger, Instant::now()); self.overview_mode = OverviewMode::Started(trigger, Instant::now());
} }
@ -2344,7 +2343,7 @@ impl Shell {
} else { } else {
self.resize_mode = ResizeMode::Started(pattern, Instant::now(), direction); self.resize_mode = ResizeMode::Started(pattern, Instant::now(), direction);
} }
self.resize_indicator = Some(resize_indicator( self.resize_indicator = Some(ResizeIndicator::new(
direction, direction,
config, config,
evlh, evlh,
@ -3668,6 +3667,8 @@ impl Shell {
return None; return None;
}; };
let mut theme = self.theme.clone();
theme.transparent = theme.cosmic().frosted_windows;
let grab = MenuGrab::new( let grab = MenuGrab::new(
GrabStartData::Pointer(start_data), GrabStartData::Pointer(start_data),
seat, seat,
@ -3676,7 +3677,7 @@ impl Shell {
MenuAlignment::CORNER, MenuAlignment::CORNER,
None, None,
evlh.clone(), evlh.clone(),
self.theme.clone(), theme,
); );
Some((grab, Focus::Keep)) Some((grab, Focus::Keep))

View file

@ -11,7 +11,7 @@ use cosmic_comp_config::ZoomMovement;
use cosmic_config::ConfigSet; use cosmic_config::ConfigSet;
use keyframe::{ease, functions::Linear}; use keyframe::{ease, functions::Linear};
use smithay::{ use smithay::{
backend::renderer::{ImportMem, Renderer, element::memory::MemoryRenderBufferRenderElement}, backend::renderer::ImportMem,
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{ input::{
Seat, Seat,
@ -32,9 +32,10 @@ use smithay::{
use tracing::error; use tracing::error;
use crate::{ use crate::{
backend::render::element::AsGlowRenderer,
state::State, state::State,
utils::{ utils::{
iced::{IcedElement, Program}, iced::{IcedElement, IcedRenderElement, Program},
prelude::*, prelude::*,
tween::EasePoint, tween::EasePoint,
}, },
@ -71,8 +72,9 @@ impl OutputZoomState {
increment: u32, increment: u32,
movement: ZoomMovement, movement: ZoomMovement,
loop_handle: LoopHandle<'static, State>, loop_handle: LoopHandle<'static, State>,
theme: cosmic::Theme, mut theme: cosmic::Theme,
) -> OutputZoomState { ) -> OutputZoomState {
theme.transparent = theme.cosmic().frosted_system_interface;
let cursor_position = seat.get_pointer().unwrap().current_location().as_global(); let cursor_position = seat.get_pointer().unwrap().current_location().as_global();
let output_geometry = output.geometry().to_f64(); let output_geometry = output.geometry().to_f64();
let focal_point = if output_geometry.contains(cursor_position) { let focal_point = if output_geometry.contains(cursor_position) {
@ -108,8 +110,7 @@ impl OutputZoomState {
let program = ZoomProgram::new(level, movement, increment); let program = ZoomProgram::new(level, movement, increment);
let element = IcedElement::new(program, Size::default(), loop_handle, theme); let element = IcedElement::new(program, Size::default(), loop_handle, theme);
let mut size = element.minimum_size(); let mut size = element.minimum_size();
size.w = (size.w + 32/*TODO: figure out why iced is calculating too little*/) size.w = size.w.min(output_geometry.size.w.round() as i32);
.min(output_geometry.size.w.round() as i32);
element.set_activate(true); element.set_activate(true);
element.resize(size); element.resize(size);
element.output_enter(output, Rectangle::new(Point::from((0, 0)), size)); element.output_enter(output, Rectangle::new(Point::from((0, 0)), size));
@ -196,9 +197,9 @@ impl OutputZoomState {
&mut self, &mut self,
renderer: &mut R, renderer: &mut R,
output: &Output, output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>), push: &mut dyn FnMut(IcedRenderElement<R>),
) where ) where
R: Renderer + ImportMem, R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
let size = self.element.current_size().to_f64(); let size = self.element.current_size().to_f64();
@ -216,7 +217,11 @@ impl OutputZoomState {
location, location,
scale.fractional_scale().into(), scale.fractional_scale().into(),
1.0, 1.0,
self.element
.with_theme(|theme| theme.cosmic().radius_s())
.map(|x| x.round() as u8),
push, push,
None,
) )
} }
} }
@ -390,12 +395,9 @@ impl ZoomState {
None None
} }
pub fn render<R>( pub fn render<R>(renderer: &mut R, output: &Output, push: &mut dyn FnMut(IcedRenderElement<R>))
renderer: &mut R, where
output: &Output, R: AsGlowRenderer + ImportMem,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
let output_state = output.user_data().get::<Mutex<OutputZoomState>>().unwrap(); let output_state = output.user_data().get::<Mutex<OutputZoomState>>().unwrap();
@ -515,7 +517,7 @@ impl Program for ZoomProgram {
.padding(8) .padding(8)
.class(theme::Container::custom(|theme| { .class(theme::Container::custom(|theme| {
let cosmic = theme.cosmic(); let cosmic = theme.cosmic();
let component = &cosmic.background(false).component; let component = &cosmic.background(theme.transparent).component;
iced_widget::container::Style { iced_widget::container::Style {
snap: true, snap: true,
icon_color: Some(component.on.into()), icon_color: Some(component.on.into()),
@ -591,6 +593,8 @@ impl Program for ZoomProgram {
let level = output_state_ref.level; let level = output_state_ref.level;
std::mem::drop(output_state_ref); std::mem::drop(output_state_ref);
let mut theme = state.common.theme.clone();
theme.transparent = theme.cosmic().frosted_system_interface;
let grab = MenuGrab::new( let grab = MenuGrab::new(
start_data, start_data,
&seat, &seat,
@ -703,7 +707,7 @@ impl Program for ZoomProgram {
), ),
Some(level.min(4.)), Some(level.min(4.)),
state.common.event_loop_handle.clone(), state.common.event_loop_handle.clone(),
state.common.theme.clone(), theme,
); );
std::mem::drop(shell); std::mem::drop(shell);
@ -756,6 +760,8 @@ impl Program for ZoomProgram {
let level = output_state_ref.level; let level = output_state_ref.level;
std::mem::drop(output_state_ref); std::mem::drop(output_state_ref);
let mut theme = state.common.theme.clone();
theme.transparent = theme.cosmic().frosted_system_interface;
let grab = MenuGrab::new( let grab = MenuGrab::new(
start_data, start_data,
&seat, &seat,
@ -788,7 +794,7 @@ impl Program for ZoomProgram {
MenuAlignment::PREFER_CENTERED, MenuAlignment::PREFER_CENTERED,
Some(level.min(4.)), Some(level.min(4.)),
state.common.event_loop_handle.clone(), state.common.event_loop_handle.clone(),
state.common.theme.clone(), theme,
); );
std::mem::drop(shell); std::mem::drop(shell);