element: Refactor element acquisition to be push based

This commit is contained in:
Victoria Brekenfeld 2026-03-04 18:57:37 +01:00 committed by Victoria Brekenfeld
parent 178c6593dc
commit e4c0716951
18 changed files with 1096 additions and 1137 deletions

View file

@ -18,10 +18,7 @@ use cosmic::{
use smithay::{
backend::{
input::{ButtonState, TouchSlot},
renderer::{
ImportMem, Renderer,
element::{AsRenderElements, memory::MemoryRenderBufferRenderElement},
},
renderer::{ImportMem, Renderer, element::memory::MemoryRenderBufferRenderElement},
},
desktop::space::SpaceElement,
input::{
@ -65,29 +62,28 @@ pub struct MenuGrabState {
pub type SeatMenuGrabState = Mutex<Option<MenuGrabState>>;
impl MenuGrabState {
pub fn render<I, R>(&self, renderer: &mut R, output: &Output) -> Vec<I>
where
pub fn render<R>(
&self,
renderer: &mut R,
output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static,
I: From<MemoryRenderBufferRenderElement<R>>,
{
let scale = output.current_scale().fractional_scale();
self.elements
.lock()
.unwrap()
.iter()
.flat_map(|elem| {
elem.iced.render_elements(
renderer,
elem.position
.to_local(output)
.as_logical()
.to_physical_precise_round(scale),
scale.into(),
1.0,
)
})
.collect()
for elem in self.elements.lock().unwrap().iter() {
elem.iced.push_render_elements(
renderer,
elem.position
.to_local(output)
.as_logical()
.to_physical_precise_round(scale),
scale.into(),
1.0,
push,
)
}
}
pub fn is_in_screen_space(&self) -> bool {

View file

@ -19,13 +19,14 @@ use crate::{
use calloop::LoopHandle;
use cosmic::theme::CosmicTheme;
use smallvec::SmallVec;
use smithay::{
backend::{
drm::DrmNode,
input::ButtonState,
renderer::{
ImportAll, ImportMem, Renderer,
element::{AsRenderElements, RenderElement, utils::RescaleRenderElement},
element::{RenderElement, utils::RescaleRenderElement},
},
},
desktop::{WindowSurfaceType, layer_map_for_output, space::SpaceElement},
@ -69,18 +70,17 @@ pub struct MoveGrabState {
impl MoveGrabState {
#[profiling::function]
pub fn render<I, R>(
pub fn render<R>(
&self,
renderer: &mut R,
output: &Output,
theme: &CosmicTheme,
scanout_node: Option<DrmNode>,
) -> Vec<I>
where
push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
I: From<CosmicMappedRenderElement<R>>,
{
let scale = if self.previous == ManagedLayer::Tiling {
0.6 + ((1.0
@ -105,7 +105,7 @@ impl MoveGrabState {
.intersection(window_geo)
.is_none()
{
return Vec::new();
return;
}
let output_scale: Scale<f64> = output.current_scale().fractional_scale().into();
@ -115,13 +115,32 @@ impl MoveGrabState {
+ self.window_offset
- scaling_offset;
for (indicator, location) in self.stacking_indicator.iter() {
indicator.push_render_elements(
renderer,
location.to_physical_precise_round(output_scale),
output_scale,
1.0,
&mut |elem| push(elem.into()),
);
}
self.window.push_popup_render_elements::<R>(
renderer,
(render_location - self.window.geometry().loc).to_physical_precise_round(output_scale),
output_scale,
alpha,
scanout_node,
push,
);
let active_window_hint = crate::theme::active_window_hint(theme);
let radius = self
.element()
.corner_radius(window_geo.size, self.indicator_thickness);
let focus_element = if self.indicator_thickness > 0 {
Some(CosmicMappedRenderElement::from(
if self.indicator_thickness > 0 {
push(
IndicatorShader::focus_element(
renderer,
Key::Window(Usage::MoveGrabIndicator, self.window.key()),
@ -144,12 +163,57 @@ impl MoveGrabState {
active_window_hint.green,
active_window_hint.blue,
],
),
))
} else {
None
)
.into(),
)
}
let map_window_element = |elem| match elem {
CosmicMappedRenderElement::Stack(stack) => {
CosmicMappedRenderElement::GrabbedStack(RescaleRenderElement::from_element(
stack,
render_location
.to_physical_precise_round(output.current_scale().fractional_scale()),
scale,
))
}
CosmicMappedRenderElement::Window(window) => {
CosmicMappedRenderElement::GrabbedWindow(RescaleRenderElement::from_element(
window,
render_location
.to_physical_precise_round(output.current_scale().fractional_scale()),
scale,
))
}
x => x,
};
let mut lower_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
self.window.push_render_elements(
renderer,
(render_location - self.window.geometry().loc).to_physical_precise_round(output_scale),
None,
output_scale,
alpha,
Some(false),
scanout_node,
&mut |elem| push(map_window_element(elem)),
&mut |elem| lower_elements.push(map_window_element(elem)),
);
if let Some(shadow_element) = self.window.shadow_render_element(
renderer,
(render_location - self.window.geometry().loc).to_physical_precise_round(output_scale),
None,
output_scale,
scale,
alpha,
) {
push(shadow_element);
}
for elem in lower_elements.into_iter() {
push(elem);
}
let non_exclusive_geometry = {
let layers = layer_map_for_output(output);
layers.non_exclusive_zone()
@ -158,119 +222,46 @@ impl MoveGrabState {
let gaps = (theme.gaps.0 as i32, theme.gaps.1 as i32);
let thickness = self.indicator_thickness.max(1);
let snapping_indicator = match &self.snapping_zone {
Some(t) if &self.cursor_output == output => {
let base_color = theme.palette.neutral_9;
let overlay_geometry = t.overlay_geometry(non_exclusive_geometry, gaps);
vec![
CosmicMappedRenderElement::from(IndicatorShader::element(
renderer,
Key::Window(Usage::SnappingIndicator, self.window.key()),
overlay_geometry,
thickness,
[
theme.radius_s()[0] as u8,
theme.radius_s()[1] as u8,
theme.radius_s()[2] as u8,
theme.radius_s()[3] as u8,
],
1.0,
output_scale.x,
[
active_window_hint.red,
active_window_hint.green,
active_window_hint.blue,
],
)),
CosmicMappedRenderElement::from(BackdropShader::element(
renderer,
Key::Window(Usage::SnappingIndicator, self.window.key()),
t.overlay_geometry(non_exclusive_geometry, gaps),
theme.radius_s()[0], // TODO: Fix once shaders support 4 corner radii customization
0.4,
[base_color.red, base_color.green, base_color.blue],
)),
]
}
_ => vec![],
};
if let Some(t) = &self.snapping_zone
&& &self.cursor_output == output
{
let base_color = theme.palette.neutral_9;
let overlay_geometry = t.overlay_geometry(non_exclusive_geometry, gaps);
let w_elements = self
.window
.render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
(render_location - self.window.geometry().loc)
.to_physical_precise_round(output_scale),
None,
output_scale,
alpha,
Some(false),
scanout_node,
);
let p_elements = self
.window
.popup_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
(render_location - self.window.geometry().loc)
.to_physical_precise_round(output_scale),
output_scale,
alpha,
scanout_node,
);
let shadow_element = self.window.shadow_render_element(
renderer,
(render_location - self.window.geometry().loc).to_physical_precise_round(output_scale),
None,
output_scale,
scale,
alpha,
);
self.stacking_indicator
.iter()
.flat_map(|(indicator, location)| {
indicator.render_elements(
push(
IndicatorShader::element(
renderer,
location.to_physical_precise_round(output_scale),
output_scale,
Key::Window(Usage::SnappingIndicator, self.window.key()),
overlay_geometry,
thickness,
[
theme.radius_s()[0] as u8,
theme.radius_s()[1] as u8,
theme.radius_s()[2] as u8,
theme.radius_s()[3] as u8,
],
1.0,
output_scale.x,
[
active_window_hint.red,
active_window_hint.green,
active_window_hint.blue,
],
)
})
.chain(p_elements)
.chain(focus_element)
.chain(
w_elements
.into_iter()
.chain(shadow_element)
.map(|elem| match elem {
CosmicMappedRenderElement::Stack(stack) => {
CosmicMappedRenderElement::GrabbedStack(
RescaleRenderElement::from_element(
stack,
render_location.to_physical_precise_round(
output.current_scale().fractional_scale(),
),
scale,
),
)
}
CosmicMappedRenderElement::Window(window) => {
CosmicMappedRenderElement::GrabbedWindow(
RescaleRenderElement::from_element(
window,
render_location.to_physical_precise_round(
output.current_scale().fractional_scale(),
),
scale,
),
)
}
x => x,
}),
.into(),
);
push(
BackdropShader::element(
renderer,
Key::Window(Usage::SnappingIndicator, self.window.key()),
t.overlay_geometry(non_exclusive_geometry, gaps),
theme.radius_s()[0], // TODO: Fix once shaders support 4 corner radii customization
0.4,
[base_color.red, base_color.green, base_color.blue],
)
.into(),
)
.chain(snapping_indicator)
.map(I::from)
.collect()
}
}
pub fn element(&self) -> CosmicMapped {