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

5
Cargo.lock generated
View file

@ -841,6 +841,7 @@ dependencies = [
"sanitize-filename", "sanitize-filename",
"serde", "serde",
"serde_json", "serde_json",
"smallvec",
"smithay", "smithay",
"smithay-egui", "smithay-egui",
"thiserror 2.0.18", "thiserror 2.0.18",
@ -4790,9 +4791,9 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.15.1" version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]] [[package]]
name = "smithay" name = "smithay"

View file

@ -83,6 +83,7 @@ logind-zbus = { version = "5.3.2", optional = true }
futures-executor = { version = "0.3.32" } futures-executor = { version = "0.3.32" }
futures-util = "0.3.32" futures-util = "0.3.32"
cgmath = "0.18.0" cgmath = "0.18.0"
smallvec = "1.15.2"
[dependencies.id_tree] [dependencies.id_tree]
branch = "feature/copy_clone" branch = "feature/copy_clone"

View file

@ -3,7 +3,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::AsGlowRenderer, element::AsGlowRenderer,
wayland::{SurfaceRenderElement, render_elements_from_surface_tree}, wayland::{SurfaceRenderElement, push_render_elements_from_surface_tree},
}, },
utils::prelude::*, utils::prelude::*,
wayland::handlers::compositor::FRAME_TIME_FILTER, wayland::handlers::compositor::FRAME_TIME_FILTER,
@ -185,8 +185,8 @@ pub fn draw_surface_cursor<R>(
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
location: Point<f64, Logical>, location: Point<f64, Logical>,
scale: impl Into<Scale<f64>>, scale: impl Into<Scale<f64>>,
) -> Vec<(CursorRenderElement<R>, Point<i32, Physical>)> push: &mut dyn FnMut(CursorRenderElement<R>, Point<i32, Physical>),
where ) where
R: Renderer + ImportAll + AsGlowRenderer, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
{ {
@ -202,7 +202,7 @@ where
.to_physical_precise_round(scale) .to_physical_precise_round(scale)
}); });
render_elements_from_surface_tree( push_render_elements_from_surface_tree(
renderer, renderer,
surface, surface,
location.to_physical(scale).to_i32_round(), location.to_physical(scale).to_i32_round(),
@ -212,10 +212,9 @@ where
false, false,
[0; 4], [0; 4],
Kind::Cursor, Kind::Cursor,
) &mut |elem| push(elem.into(), h),
.into_iter() None,
.map(|elem| (elem, h)) );
.collect()
} }
#[profiling::function] #[profiling::function]
@ -224,8 +223,8 @@ pub fn draw_dnd_icon<R>(
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
location: Point<f64, Logical>, location: Point<f64, Logical>,
scale: impl Into<Scale<f64>>, scale: impl Into<Scale<f64>>,
) -> Vec<SurfaceRenderElement<R>> push: &mut dyn FnMut(SurfaceRenderElement<R>),
where ) where
R: Renderer + ImportAll + AsGlowRenderer, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
{ {
@ -236,7 +235,7 @@ where
); );
} }
let scale = scale.into(); let scale = scale.into();
render_elements_from_surface_tree( push_render_elements_from_surface_tree(
renderer, renderer,
surface, surface,
location.to_physical(scale).to_i32_round(), location.to_physical(scale).to_i32_round(),
@ -246,7 +245,9 @@ where
false, false,
[0; 4], [0; 4],
FRAME_TIME_FILTER, FRAME_TIME_FILTER,
) push,
None,
);
} }
pub type CursorState = Mutex<CursorStateInner>; pub type CursorState = Mutex<CursorStateInner>;
@ -330,8 +331,8 @@ pub fn draw_cursor<R>(
buffer_scale: f64, buffer_scale: f64,
time: Time<Monotonic>, time: Time<Monotonic>,
draw_default: bool, draw_default: bool,
) -> Vec<(CursorRenderElement<R>, Point<i32, Physical>)> push: &mut dyn FnMut(CursorRenderElement<R>, Point<i32, Physical>),
where ) where
R: Renderer + ImportMem + ImportAll + AsGlowRenderer, R: Renderer + ImportMem + ImportAll + AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
@ -343,7 +344,7 @@ where
let state = &mut *state_ref; let state = &mut *state_ref;
if state.hidden { if state.hidden {
return Vec::new(); return;
} }
let named_cursor = state.current_cursor.or(match cursor_status { let named_cursor = state.current_cursor.or(match cursor_status {
@ -352,7 +353,7 @@ where
}); });
if let Some(current_cursor) = named_cursor { if let Some(current_cursor) = named_cursor {
if !draw_default && current_cursor == CursorIcon::Default { if !draw_default && current_cursor == CursorIcon::Default {
return Vec::new(); return;
} }
let integer_scale = (scale.x.max(scale.y) * buffer_scale).ceil() as u32; let integer_scale = (scale.x.max(scale.y) * buffer_scale).ceil() as u32;
@ -389,7 +390,7 @@ where
); );
state.current_image = Some(frame); state.current_image = Some(frame);
return vec![( push(
CursorRenderElement::Static( CursorRenderElement::Static(
MemoryRenderBufferRenderElement::from_buffer( MemoryRenderBufferRenderElement::from_buffer(
renderer, renderer,
@ -403,11 +404,9 @@ where
.expect("Failed to import cursor bitmap"), .expect("Failed to import cursor bitmap"),
), ),
hotspot.to_physical_precise_round(scale), hotspot.to_physical_precise_round(scale),
)]; );
} else if let CursorImageStatus::Surface(ref wl_surface) = cursor_status { } else if let CursorImageStatus::Surface(ref wl_surface) = cursor_status {
return draw_surface_cursor(renderer, wl_surface, location, scale); draw_surface_cursor(renderer, wl_surface, location, scale, push);
} else {
Vec::new()
} }
} }

View file

@ -17,7 +17,11 @@ use crate::{
render::{ render::{
element::DamageElement, element::DamageElement,
shadow::{SHADOW_SHADER, ShadowShader}, shadow::{SHADOW_SHADER, ShadowShader},
wayland::clipped_surface::{CLIPPING_SHADER, ClippingShader}, wayland::{
SurfaceRenderElement,
clipped_surface::{CLIPPING_SHADER, ClippingShader},
push_render_elements_from_surface_tree,
},
}, },
}, },
config::ScreenFilter, config::ScreenFilter,
@ -47,11 +51,10 @@ use smithay::{
allocator::Fourcc, allocator::Fourcc,
drm::{DrmDeviceFd, DrmNode}, drm::{DrmDeviceFd, DrmNode},
renderer::{ renderer::{
Color32F, ImportAll, Offscreen, Renderer, Texture, TextureFilter, Color32F, Offscreen, Texture, TextureFilter,
damage::{Error as RenderError, OutputDamageTracker, RenderOutputResult}, damage::{Error as RenderError, OutputDamageTracker, RenderOutputResult},
element::{ element::{
Element, Id, Kind, RenderElement, WeakId, Element, Id, Kind, RenderElement, WeakId,
surface::{WaylandSurfaceRenderElement, render_elements_from_surface_tree},
texture::{TextureRenderBuffer, TextureRenderElement}, texture::{TextureRenderBuffer, TextureRenderElement},
utils::{ utils::{
ConstrainAlign, ConstrainScaleBehavior, CropRenderElement, Relocate, ConstrainAlign, ConstrainScaleBehavior, CropRenderElement, Relocate,
@ -68,6 +71,7 @@ use smithay::{
sync::SyncPoint, sync::SyncPoint,
}, },
}, },
desktop::utils::bbox_from_surface_tree,
input::Seat, input::Seat,
output::{Output, OutputModeSource, OutputNoMode}, output::{Output, OutputModeSource, OutputNoMode},
utils::{ utils::{
@ -475,8 +479,8 @@ pub fn cursor_elements<'a, 'frame, R>(
mode: CursorMode, mode: CursorMode,
exclude_dnd_icon: bool, exclude_dnd_icon: bool,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicElement<R>> push: &mut dyn FnMut(CosmicElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -490,7 +494,6 @@ where
) )
}) })
.unwrap_or_else(|| ((0., 0.).into(), 1.)); .unwrap_or_else(|| ((0., 0.).into(), 1.));
let mut elements = Vec::new();
for seat in seats { for seat in seats {
let pointer = match seat.get_pointer() { let pointer = match seat.get_pointer() {
@ -500,19 +503,16 @@ where
let location = pointer.current_location() - output.current_location().to_f64(); let location = pointer.current_location() - output.current_location().to_f64();
if mode != CursorMode::None { if mode != CursorMode::None {
elements.extend( cursor::draw_cursor(
cursor::draw_cursor( renderer,
renderer, seat,
seat, location,
location, scale.into(),
scale.into(), zoom_scale,
zoom_scale, now,
now, mode != CursorMode::NotDefault,
mode != CursorMode::NotDefault, &mut |elem, hotspot| {
) push(CosmicElement::Cursor(RescaleRenderElement::from_element(
.into_iter()
.map(|(elem, hotspot)| {
CosmicElement::Cursor(RescaleRenderElement::from_element(
RelocateRenderElement::from_element( RelocateRenderElement::from_element(
elem, elem,
Point::from((-hotspot.x, -hotspot.y)), Point::from((-hotspot.x, -hotspot.y)),
@ -523,70 +523,54 @@ where
.to_physical(output.current_scale().fractional_scale()) .to_physical(output.current_scale().fractional_scale())
.to_i32_round(), .to_i32_round(),
zoom_scale, zoom_scale,
)) )))
}), },
); );
} }
if !exclude_dnd_icon && let Some(dnd_icon) = get_dnd_icon(seat) { if !exclude_dnd_icon && let Some(dnd_icon) = get_dnd_icon(seat) {
elements.extend( cursor::draw_dnd_icon(
cursor::draw_dnd_icon( renderer,
renderer, &dnd_icon.surface,
&dnd_icon.surface, (location + dnd_icon.offset.to_f64()).to_i32_round(),
(location + dnd_icon.offset.to_f64()).to_i32_round(), scale,
scale, &mut |elem| push(CosmicElement::Dnd(elem)),
)
.into_iter()
.map(CosmicElement::Dnd),
); );
} }
let theme = theme.cosmic(); let theme = theme.cosmic();
if let Some(grab_elements) = seat if let Some(grab_state) = seat
.user_data() .user_data()
.get::<SeatMoveGrabState>() .get::<SeatMoveGrabState>()
.unwrap() .unwrap()
.lock() .lock()
.unwrap() .unwrap()
.as_ref() .as_ref()
.map(|state| {
state.render::<CosmicMappedRenderElement<R>, R>(
renderer,
output,
theme,
scanout_node,
)
})
{ {
elements.extend(grab_elements.into_iter().map(|elem| { grab_state.render(renderer, output, theme, scanout_node, &mut |elem| {
CosmicElement::MoveGrab(RescaleRenderElement::from_element( push(CosmicElement::MoveGrab(RescaleRenderElement::from_element(
elem, elem,
focal_point focal_point
.as_logical() .as_logical()
.to_physical(output.current_scale().fractional_scale()) .to_physical(output.current_scale().fractional_scale())
.to_i32_round(), .to_i32_round(),
zoom_scale, zoom_scale,
)) )));
})); })
} }
if let Some((grab_elements, should_scale)) = seat if let Some(grab_state) = seat
.user_data() .user_data()
.get::<SeatMenuGrabState>() .get::<SeatMenuGrabState>()
.unwrap() .unwrap()
.lock() .lock()
.unwrap() .unwrap()
.as_ref() .as_ref()
.map(|state| {
(
state.render::<CosmicMappedRenderElement<R>, R>(renderer, output),
!state.is_in_screen_space(),
)
})
{ {
elements.extend(grab_elements.into_iter().map(|elem| { let should_scale = !grab_state.is_in_screen_space();
CosmicElement::MoveGrab(RescaleRenderElement::from_element( grab_state.render(renderer, output, &mut |elem| {
elem, push(CosmicElement::MoveGrab(RescaleRenderElement::from_element(
elem.into(),
if should_scale { if should_scale {
focal_point focal_point
.as_logical() .as_logical()
@ -596,12 +580,10 @@ where
Point::from((0, 0)) Point::from((0, 0))
}, },
if should_scale { zoom_scale } else { 1.0 }, if should_scale { zoom_scale } else { 1.0 },
)) )));
})); })
} }
} }
elements
} }
#[cfg(not(feature = "debug"))] #[cfg(not(feature = "debug"))]
@ -729,7 +711,7 @@ where
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let mut elements = Vec::new(); let mut elements = Vec::<CosmicElement<R>>::new();
let shell_ref = shell.read(); let shell_ref = shell.read();
let seats = shell_ref.seats.iter().cloned().collect::<Vec<_>>(); let seats = shell_ref.seats.iter().cloned().collect::<Vec<_>>();
@ -742,7 +724,7 @@ where
// that is prone to deadlock with the main-thread on some grabs. // that is prone to deadlock with the main-thread on some grabs.
std::mem::drop(shell_ref); std::mem::drop(shell_ref);
elements.extend(cursor_elements( cursor_elements(
renderer, renderer,
seats.iter(), seats.iter(),
zoom_level, zoom_level,
@ -752,7 +734,8 @@ where
cursor_mode, cursor_mode,
element_filter == ElementFilter::ExcludeWorkspaceOverview, element_filter == ElementFilter::ExcludeWorkspaceOverview,
scanout_node, scanout_node,
)); &mut |elem| elements.push(elem),
);
let shell = shell.read(); let shell = shell.read();
let overview = shell.overview_mode(); let overview = shell.overview_mode();
@ -828,72 +811,81 @@ where
render_input_order::<()>(&shell, output, previous, current, element_filter, |stage| { render_input_order::<()>(&shell, output, previous, current, element_filter, |stage| {
match stage { match stage {
Stage::ZoomUI => { Stage::ZoomUI => {
elements.extend(ZoomState::render(renderer, output)); ZoomState::render(renderer, output, &mut |elem| {
elements.push(CosmicElement::Zoom(elem))
});
} }
Stage::SessionLock(lock_surface) => { Stage::SessionLock(lock_surface) => {
elements.extend( session_lock_elements(renderer, output, lock_surface, &mut |elem| {
session_lock_elements(renderer, output, lock_surface) elements.extend(crop_to_output(elem.into()).map(Into::into))
.into_iter() })
.map(Into::into)
.flat_map(crop_to_output)
.map(Into::into),
);
} }
Stage::LayerPopup { Stage::LayerPopup {
popup, location, .. popup, location, ..
} => { } => {
elements.extend( let mut geometry = popup.geometry().as_global();
render_elements_from_surface_tree::<_, WorkspaceRenderElement<_>>( geometry.loc += location;
renderer,
popup.wl_surface(), push_render_elements_from_surface_tree(
location renderer,
.to_local(output) popup.wl_surface(),
.as_logical() location
.to_physical_precise_round(scale), .to_local(output)
Scale::from(scale), .as_logical()
1.0, .to_physical_precise_round(scale),
FRAME_TIME_FILTER, geometry.to_local(output).as_logical().to_f64(),
) Scale::from(scale),
.into_iter() 1.0,
.flat_map(crop_to_output) false,
.map(Into::into), [0; 4],
); FRAME_TIME_FILTER,
&mut |elem| elements.extend(crop_to_output(elem.into()).map(Into::into)),
None,
)
} }
Stage::LayerSurface { layer, location } => { Stage::LayerSurface { layer, location } => {
elements.extend( let mut geometry = layer.geometry().as_global();
render_elements_from_surface_tree::<_, WorkspaceRenderElement<_>>( geometry.loc += location;
renderer,
layer.wl_surface(), push_render_elements_from_surface_tree(
location renderer,
.to_local(output) layer.wl_surface(),
.as_logical() location
.to_physical_precise_round(scale), .to_local(output)
Scale::from(scale), .as_logical()
1.0, .to_physical_precise_round(scale),
FRAME_TIME_FILTER, geometry.to_local(output).as_logical().to_f64(),
) Scale::from(scale),
.into_iter() 1.0,
.flat_map(crop_to_output) false,
.map(Into::into), [0; 4],
FRAME_TIME_FILTER,
&mut |elem| elements.extend(crop_to_output(elem.into()).map(Into::into)),
None,
); );
} }
Stage::OverrideRedirect { surface, location } => { Stage::OverrideRedirect { surface, location } => {
elements.extend(surface.wl_surface().into_iter().flat_map(|surface| { if let Some(wl_surface) = surface.wl_surface() {
render_elements_from_surface_tree::<_, WorkspaceRenderElement<_>>( let mut geometry = surface.geometry().as_global();
geometry.loc += location;
push_render_elements_from_surface_tree(
renderer, renderer,
&surface, &wl_surface,
location location
.to_local(output) .to_local(output)
.as_logical() .as_logical()
.to_physical_precise_round(scale), .to_physical_precise_round(scale),
geometry.to_local(output).as_logical().to_f64(),
Scale::from(scale), Scale::from(scale),
1.0, 1.0,
false,
[0; 4],
FRAME_TIME_FILTER, FRAME_TIME_FILTER,
) &mut |elem| elements.extend(crop_to_output(elem.into()).map(Into::into)),
.into_iter() None,
.flat_map(crop_to_output) );
.map(Into::into) }
}));
} }
Stage::StickyPopups(layout) => { Stage::StickyPopups(layout) => {
let alpha = match &overview.0 { let alpha = match &overview.0 {
@ -914,14 +906,11 @@ where
OverviewMode::None => 1.0, OverviewMode::None => 1.0,
}; };
elements.extend( layout.render_popups(renderer, alpha, scanout_node, &mut |elem| {
layout if let Some(elem) = crop_to_output(elem.into()) {
.render_popups(renderer, alpha, scanout_node) elements.push(elem.into())
.into_iter() }
.map(Into::into) });
.flat_map(crop_to_output)
.map(Into::into),
);
} }
Stage::Sticky(layout) => { Stage::Sticky(layout) => {
let alpha = match &overview.0 { let alpha = match &overview.0 {
@ -946,82 +935,66 @@ where
.then_some(last_active_seat) .then_some(last_active_seat)
.map(|seat| workspace.focus_stack.get(seat)); .map(|seat| workspace.focus_stack.get(seat));
elements.extend( layout.render(
layout renderer,
.render( current_focus.as_ref().and_then(|stack| {
renderer, stack.last().and_then(|t| match t {
current_focus.as_ref().and_then(|stack| { FocusTarget::Window(w) => Some(w),
stack.last().and_then(|t| match t { _ => None,
FocusTarget::Window(w) => Some(w), })
_ => None, }),
}) resize_indicator.clone(),
}), active_hint,
resize_indicator.clone(), alpha,
active_hint, theme.cosmic(),
alpha, scanout_node,
theme.cosmic(), &mut |elem| {
scanout_node, if let Some(elem) = crop_to_output(elem.into()) {
) elements.push(elem.into())
.into_iter() }
.map(Into::into) },
.flat_map(crop_to_output) );
.map(Into::into),
)
} }
Stage::WorkspacePopups { workspace, offset } => { Stage::WorkspacePopups { workspace, offset } => {
elements.extend( workspace.render_popups(
match workspace.render_popups( renderer,
renderer, last_active_seat,
last_active_seat, !move_active && is_active_space,
!move_active && is_active_space, overview.clone(),
overview.clone(), theme.cosmic(),
theme.cosmic(), scanout_node,
scanout_node, &mut |elem| {
) { if let Some(elem) = crop_to_output(elem) {
Ok(elements) => { elements.push(CosmicElement::Workspace(
elements RelocateRenderElement::from_element(
.into_iter() elem,
.flat_map(crop_to_output) offset.to_physical_precise_round(scale),
.map(|element| { Relocate::Relative,
CosmicElement::Workspace(RelocateRenderElement::from_element( ),
element, ));
offset.to_physical_precise_round(scale),
Relocate::Relative,
))
})
}
Err(_) => {
return ControlFlow::Break(Err(OutputNoMode));
} }
}, },
); );
} }
Stage::Workspace { workspace, offset } => { Stage::Workspace { workspace, offset } => {
elements.extend( workspace.render(
match workspace.render( renderer,
renderer, last_active_seat,
last_active_seat, !move_active && is_active_space,
!move_active && is_active_space, overview.clone(),
overview.clone(), resize_indicator.clone(),
resize_indicator.clone(), active_hint,
active_hint, theme.cosmic(),
theme.cosmic(), scanout_node,
scanout_node, &mut |elem| {
) { if let Some(elem) = crop_to_output(elem) {
Ok(elements) => { elements.push(CosmicElement::Workspace(
elements RelocateRenderElement::from_element(
.into_iter() elem,
.flat_map(crop_to_output) offset.to_physical_precise_round(scale),
.map(|element| { Relocate::Relative,
CosmicElement::Workspace(RelocateRenderElement::from_element( ),
element, ));
offset.to_physical_precise_round(scale),
Relocate::Relative,
))
})
}
Err(_) => {
return ControlFlow::Break(Err(OutputNoMode));
} }
}, },
); );
@ -1038,23 +1011,26 @@ fn session_lock_elements<R>(
renderer: &mut R, renderer: &mut R,
output: &Output, output: &Output,
lock_surface: Option<&LockSurface>, lock_surface: Option<&LockSurface>,
) -> Vec<WaylandSurfaceRenderElement<R>> push: &mut dyn FnMut(SurfaceRenderElement<R>),
where ) where
R: Renderer + ImportAll, R: AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
{ {
if let Some(surface) = lock_surface { if let Some(surface) = lock_surface {
let scale = Scale::from(output.current_scale().fractional_scale()); let scale = Scale::from(output.current_scale().fractional_scale());
render_elements_from_surface_tree( push_render_elements_from_surface_tree(
renderer, renderer,
surface.wl_surface(), surface.wl_surface(),
(0, 0), (0, 0),
bbox_from_surface_tree(surface.wl_surface(), (0, 0)).to_f64(),
scale, scale,
1.0, 1.0,
false,
[0; 4],
FRAME_TIME_FILTER, FRAME_TIME_FILTER,
push,
None,
) )
} else {
Vec::new()
} }
} }

View file

@ -23,7 +23,7 @@ render_elements! {
Wayland=WaylandSurfaceRenderElement<R>, Wayland=WaylandSurfaceRenderElement<R>,
} }
pub fn render_elements_from_surface_tree<R, E>( pub fn push_render_elements_from_surface_tree<R>(
renderer: &mut R, renderer: &mut R,
main_surface: &wl_surface::WlSurface, main_surface: &wl_surface::WlSurface,
location: impl Into<Point<i32, Physical>>, location: impl Into<Point<i32, Physical>>,
@ -33,17 +33,17 @@ pub fn render_elements_from_surface_tree<R, E>(
should_clip: bool, should_clip: bool,
radii: [u8; 4], radii: [u8; 4],
kind: impl Into<KindEvaluation>, kind: impl Into<KindEvaluation>,
) -> Vec<E> push_above: &mut dyn FnMut(SurfaceRenderElement<R>),
where mut push_below: Option<&mut dyn FnMut(SurfaceRenderElement<R>)>,
) where
R: Renderer + ImportAll + AsGlowRenderer, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
E: From<SurfaceRenderElement<R>>,
{ {
let location = location.into().to_f64(); let location = location.into().to_f64();
let geometry = geometry.into().to_f64(); let geometry = geometry.into().to_f64();
let scale = scale.into(); let scale = scale.into();
let kind = kind.into(); let kind = kind.into();
let mut surfaces: Vec<E> = Vec::new(); let mut passed_main = false;
compositor::with_surface_tree_downward( compositor::with_surface_tree_downward(
main_surface, main_surface,
@ -94,7 +94,13 @@ where
} else { } else {
surface.into() surface.into()
}; };
surfaces.push(elem.into()); if let Some(push_below) = push_below.as_mut()
&& passed_main
{
push_below(elem);
} else {
push_above(elem);
}
} }
Ok(None) => {} // surface is not mapped Ok(None) => {} // surface is not mapped
Err(err) => { Err(err) => {
@ -103,9 +109,11 @@ where
}; };
} }
} }
if surface == main_surface {
passed_main = true;
}
}, },
|_, _, _| true, |_, _, _| true,
); );
surfaces
} }

View file

@ -598,42 +598,38 @@ impl CosmicMapped {
} }
} }
pub fn popup_render_elements<R, C>( pub fn push_popup_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: smithay::utils::Point<i32, smithay::utils::Physical>, location: smithay::utils::Point<i32, smithay::utils::Physical>,
scale: smithay::utils::Scale<f64>, scale: smithay::utils::Scale<f64>,
alpha: f32, alpha: f32,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
C: From<CosmicMappedRenderElement<R>>,
{ {
match &self.element { match &self.element {
CosmicMappedInternal::Stack(s) => s CosmicMappedInternal::Stack(s) => s.push_popup_render_elements(
.popup_render_elements::<R, CosmicMappedRenderElement<R>>( renderer,
renderer, location,
location, scale,
scale, alpha,
alpha, scanout_node,
scanout_node, &mut |elem| push(elem.into()),
), ),
CosmicMappedInternal::Window(w) => w CosmicMappedInternal::Window(w) => w.push_popup_render_elements(
.popup_render_elements::<R, CosmicMappedRenderElement<R>>( renderer,
renderer, location,
location, scale,
scale, alpha,
alpha, scanout_node,
scanout_node, &mut |elem| push(elem.into()),
), ),
_ => unreachable!(), _ => unreachable!(),
} }
.into_iter()
.map(C::from)
.collect()
} }
pub fn shadow_render_element<R, C>( pub fn shadow_render_element<R, C>(
@ -680,7 +676,7 @@ impl CosmicMapped {
} }
} }
pub fn render_elements<R, C>( pub fn push_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: smithay::utils::Point<i32, smithay::utils::Physical>, location: smithay::utils::Point<i32, smithay::utils::Physical>,
@ -689,15 +685,15 @@ impl CosmicMapped {
alpha: f32, alpha: f32,
scanout_override: Option<bool>, scanout_override: Option<bool>,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push_above: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where push_below: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
C: From<CosmicMappedRenderElement<R>>,
{ {
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
let mut elements = if let Some(debug) = self.debug.lock().unwrap().as_mut() { if let Some(debug) = self.debug.lock().unwrap().as_mut() {
let window = self.active_window(); let window = self.active_window();
let window_geo = window.geometry(); let window_geo = window.geometry();
let (min_size, max_size, size) = ( let (min_size, max_size, size) = (
@ -858,21 +854,15 @@ impl CosmicMapped {
scale.x, scale.x,
0.8, 0.8,
) { ) {
Ok(element) => vec![CosmicMappedRenderElement::from(element)], Ok(element) => push_above(element.into()),
Err(err) => { Err(err) => {
debug!(?err, "Error rendering debug overlay."); debug!(?err, "Error rendering debug overlay.");
Vec::new()
} }
} }
} else {
Vec::new()
}; };
#[cfg(not(feature = "debug"))]
let mut elements = Vec::new();
#[cfg_attr(not(feature = "debug"), allow(unused_mut))] match &self.element {
elements.extend(match &self.element { CosmicMappedInternal::Stack(s) => s.push_render_elements(
CosmicMappedInternal::Stack(s) => s.render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, renderer,
location, location,
max_size, max_size,
@ -880,21 +870,22 @@ impl CosmicMapped {
alpha, alpha,
scanout_override, scanout_override,
scanout_node, scanout_node,
&mut |elem| push_above(elem.into()),
&mut |elem| push_below(elem.into()),
),
CosmicMappedInternal::Window(w) => w.push_render_elements(
renderer,
location,
max_size,
scale,
alpha,
scanout_override,
scanout_node,
&mut |elem| push_above(elem.into()),
&mut |elem| push_below(elem.into()),
), ),
CosmicMappedInternal::Window(w) => w
.render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
location,
max_size,
scale,
alpha,
scanout_override,
scanout_node,
),
_ => unreachable!(), _ => unreachable!(),
}); }
elements.into_iter().map(C::from).collect()
} }
pub(crate) fn update_theme(&self, theme: cosmic::Theme) { pub(crate) fn update_theme(&self, theme: cosmic::Theme) {

View file

@ -39,8 +39,8 @@ use smithay::{
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
element::{ element::{
AsRenderElements, Element, Id as RendererId, Kind, RenderElement, Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage,
UnderlyingStorage, memory::MemoryRenderBufferRenderElement, memory::MemoryRenderBufferRenderElement,
}, },
gles::element::PixelShaderElement, gles::element::PixelShaderElement,
glow::GlowRenderer, glow::GlowRenderer,
@ -645,35 +645,31 @@ impl CosmicStack {
self.0.loop_handle() self.0.loop_handle()
} }
pub fn popup_render_elements<R, C>( pub fn push_popup_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
scale: Scale<f64>, scale: Scale<f64>,
alpha: f32, alpha: f32,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push: &mut dyn FnMut(CosmicStackRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
C: From<CosmicStackRenderElement<R>>,
{ {
let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32)); let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32));
self.0.with_program(|p| { self.0.with_program(|p| {
let windows = p.windows.lock().unwrap(); let windows = p.windows.lock().unwrap();
let active = p.active.load(Ordering::SeqCst); let active = p.active.load(Ordering::SeqCst);
windows[active] windows[active].push_popup_render_elements(
.popup_render_elements::<R, CosmicStackRenderElement<R>>( renderer,
renderer, window_loc,
window_loc, scale,
scale, alpha,
alpha, scanout_node,
scanout_node, &mut |elem| push(elem.into()),
) )
.into_iter()
.map(C::from)
.collect()
}) })
} }
@ -744,7 +740,7 @@ impl CosmicStack {
}) })
} }
pub fn render_elements<R, C>( pub fn push_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
@ -753,17 +749,17 @@ impl CosmicStack {
alpha: f32, alpha: f32,
scanout_override: Option<bool>, scanout_override: Option<bool>,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push_above: &mut dyn FnMut(CosmicStackRenderElement<R>),
where push_below: &mut dyn FnMut(CosmicStackRenderElement<R>),
) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
C: From<CosmicStackRenderElement<R>>,
{ {
if !self if !self
.0 .0
.with_program(|p| p.override_alive.load(Ordering::Acquire)) .with_program(|p| p.override_alive.load(Ordering::Acquire))
{ {
return Vec::new(); return;
} }
let geometry = self let geometry = self
@ -773,11 +769,12 @@ impl CosmicStack {
let stack_loc = location + geometry.loc; let stack_loc = location + geometry.loc;
let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32)); let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32));
let mut elements = AsRenderElements::<R>::render_elements::<CosmicStackRenderElement<R>>( self.0
&self.0, renderer, stack_loc, scale, alpha, .push_render_elements(renderer, stack_loc, scale, alpha, &mut |elem| {
); push_above(elem.into())
});
elements.extend(self.0.with_program(|p| { self.0.with_program(|p| {
let windows = p.windows.lock().unwrap(); let windows = p.windows.lock().unwrap();
let active = p.active.load(Ordering::SeqCst); let active = p.active.load(Ordering::SeqCst);
let theme = p.theme.lock().unwrap(); let theme = p.theme.lock().unwrap();
@ -804,9 +801,9 @@ impl CosmicStack {
let window_key = let window_key =
CosmicMappedKey(CosmicMappedKeyInner::Stack(Arc::downgrade(&self.0.0))); CosmicMappedKey(CosmicMappedKeyInner::Stack(Arc::downgrade(&self.0.0)));
let border = (!maximized).then(|| { if !maximized {
let (r, g, b, a) = theme.cosmic().bg_divider().into_components(); let (r, g, b, a) = theme.cosmic().bg_divider().into_components();
CosmicStackRenderElement::Border(IndicatorShader::element( push_above(CosmicStackRenderElement::Border(IndicatorShader::element(
renderer, renderer,
Key::Window(Usage::Border, window_key.clone()), Key::Window(Usage::Border, window_key.clone()),
geo.to_i32_round().as_local(), geo.to_i32_round().as_local(),
@ -815,24 +812,23 @@ impl CosmicStack {
a * alpha, a * alpha,
scale.x, scale.x,
[r, g, b], [r, g, b],
)) )));
}); };
border.into_iter().chain( let radii = radii.map(|[a, _, c, _]| [a, 0, c, 0]);
windows[active].render_elements::<R, CosmicStackRenderElement<R>>( windows[active].push_render_elements(
renderer, renderer,
window_loc, window_loc,
scale, scale,
alpha, alpha,
scanout_override, scanout_override,
scanout_node, scanout_node,
radii.is_some(), radii.is_some(),
radii.unwrap_or([0; 4]), radii.unwrap_or([0; 4]),
), &mut |elem| push_above(elem.into()),
) Some(&mut |elem| push_below(elem.into())),
})); );
});
elements.into_iter().map(C::from).collect()
} }
pub(crate) fn set_theme(&self, theme: cosmic::Theme) { pub(crate) fn set_theme(&self, theme: cosmic::Theme) {

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::AsGlowRenderer, element::AsGlowRenderer,
wayland::{SurfaceRenderElement, render_elements_from_surface_tree}, wayland::{SurfaceRenderElement, push_render_elements_from_surface_tree},
}, },
shell::focus::target::PointerFocusTarget, shell::focus::target::PointerFocusTarget,
wayland::{ wayland::{
@ -859,48 +859,47 @@ impl CosmicSurface {
self.0.user_data() self.0.user_data()
} }
pub fn popup_render_elements<R, C>( pub fn push_popup_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
scale: Scale<f64>, scale: Scale<f64>,
alpha: f32, alpha: f32,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push: &mut dyn FnMut(SurfaceRenderElement<R>),
where ) where
R: Renderer + ImportAll + AsGlowRenderer, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
C: From<SurfaceRenderElement<R>>,
{ {
match self.0.underlying_surface() { match self.0.underlying_surface() {
WindowSurface::Wayland(toplevel) => { WindowSurface::Wayland(toplevel) => {
let surface = toplevel.wl_surface(); let surface = toplevel.wl_surface();
PopupManager::popups_for_surface(surface) for (popup, popup_offset) in PopupManager::popups_for_surface(surface) {
.flat_map(move |(popup, popup_offset)| { let offset = (self.0.geometry().loc + popup_offset - popup.geometry().loc)
let offset = (self.0.geometry().loc + popup_offset - popup.geometry().loc) .to_physical_precise_round(scale);
.to_physical_precise_round(scale); let mut geometry = popup.geometry().to_f64();
let mut geometry = popup.geometry().to_f64(); geometry.loc += location.to_f64().to_logical(scale) + popup_offset.to_f64();
geometry.loc += location.to_f64().to_logical(scale) + popup_offset.to_f64();
render_elements_from_surface_tree( push_render_elements_from_surface_tree(
renderer, renderer,
popup.wl_surface(), popup.wl_surface(),
location + offset, location + offset,
geometry, geometry,
scale, scale,
alpha, alpha,
false, false,
[0; 4], [0; 4],
scanout_kind_eval(None, scanout_node), scanout_kind_eval(None, scanout_node),
) push,
}) None,
.collect() )
}
} }
WindowSurface::X11(_) => Vec::new(), WindowSurface::X11(_) => {}
} }
} }
pub fn render_elements<R, C>( pub fn push_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
@ -910,11 +909,11 @@ impl CosmicSurface {
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
should_clip: bool, should_clip: bool,
radii: [u8; 4], radii: [u8; 4],
) -> Vec<C> push_above: &mut dyn FnMut(SurfaceRenderElement<R>),
where push_below: Option<&mut dyn FnMut(SurfaceRenderElement<R>)>,
) where
R: Renderer + ImportAll + AsGlowRenderer, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
C: From<SurfaceRenderElement<R>>,
{ {
let mut geometry = self.0.geometry().to_f64(); let mut geometry = self.0.geometry().to_f64();
geometry.loc += location.to_f64().to_logical(scale); geometry.loc += location.to_f64().to_logical(scale);
@ -923,7 +922,7 @@ impl CosmicSurface {
WindowSurface::Wayland(toplevel) => { WindowSurface::Wayland(toplevel) => {
let surface = toplevel.wl_surface(); let surface = toplevel.wl_surface();
render_elements_from_surface_tree( push_render_elements_from_surface_tree(
renderer, renderer,
surface, surface,
location, location,
@ -933,14 +932,16 @@ impl CosmicSurface {
should_clip, should_clip,
radii, radii,
scanout_kind_eval(scanout_override, scanout_node), scanout_kind_eval(scanout_override, scanout_node),
push_above,
push_below,
) )
} }
WindowSurface::X11(surface) => { WindowSurface::X11(surface) => {
let Some(surface) = surface.wl_surface() else { let Some(surface) = surface.wl_surface() else {
return Vec::new(); return;
}; };
render_elements_from_surface_tree( push_render_elements_from_surface_tree(
renderer, renderer,
&surface, &surface,
location, location,
@ -950,6 +951,8 @@ impl CosmicSurface {
should_clip, should_clip,
radii, radii,
scanout_kind_eval(scanout_override, scanout_node), scanout_kind_eval(scanout_override, scanout_node),
push_above,
push_below,
) )
} }
} }

View file

@ -25,8 +25,8 @@ use smithay::{
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
element::{ element::{
AsRenderElements, Element, Id as RendererId, Kind, RenderElement, Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage,
UnderlyingStorage, memory::MemoryRenderBufferRenderElement, memory::MemoryRenderBufferRenderElement,
}, },
gles::element::PixelShaderElement, gles::element::PixelShaderElement,
glow::GlowRenderer, glow::GlowRenderer,
@ -348,18 +348,17 @@ impl CosmicWindow {
self.0.loop_handle() self.0.loop_handle()
} }
pub fn popup_render_elements<R, C>( pub fn push_popup_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
scale: Scale<f64>, scale: Scale<f64>,
alpha: f32, alpha: f32,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push: &mut dyn FnMut(CosmicWindowRenderElement<R>),
where ) where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + AsGlowRenderer + ImportAll + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
C: From<CosmicWindowRenderElement<R>>,
{ {
let has_ssd = self.0.with_program(|p| p.has_ssd(false)); let has_ssd = self.0.with_program(|p| p.has_ssd(false));
@ -370,17 +369,14 @@ impl CosmicWindow {
}; };
self.0.with_program(|p| { self.0.with_program(|p| {
p.window p.window.push_popup_render_elements(
.popup_render_elements::<R, CosmicWindowRenderElement<R>>( renderer,
renderer, window_loc,
window_loc, scale,
scale, alpha,
alpha, scanout_node,
scanout_node, &mut |elem| push(elem.into()),
) )
.into_iter()
.map(C::from)
.collect()
}) })
} }
@ -464,7 +460,7 @@ impl CosmicWindow {
}) })
} }
pub fn render_elements<R, C>( pub fn push_render_elements<R>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
@ -473,11 +469,11 @@ impl CosmicWindow {
alpha: f32, alpha: f32,
scanout_override: Option<bool>, scanout_override: Option<bool>,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> push_above: &mut dyn FnMut(CosmicWindowRenderElement<R>),
where push_below: &mut dyn FnMut(CosmicWindowRenderElement<R>),
) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
C: From<CosmicWindowRenderElement<R>>,
{ {
let (has_ssd, is_tiled, is_maximized, mut radii, appearance) = self.0.with_program(|p| { let (has_ssd, is_tiled, is_maximized, mut radii, appearance) = self.0.with_program(|p| {
( (
@ -514,8 +510,6 @@ impl CosmicWindow {
location location
}; };
let mut elements = Vec::new();
let (mut geo, bg_divider) = self.0.with_program(|p| { let (mut geo, bg_divider) = self.0.with_program(|p| {
( (
SpaceElement::geometry(&p.window).to_f64(), SpaceElement::geometry(&p.window).to_f64(),
@ -545,15 +539,15 @@ impl CosmicWindow {
scale.x, scale.x,
[r, g, b], [r, g, b],
)); ));
elements.push(elem); push_above(elem);
} }
if has_ssd { self.0.with_program(|p| {
radii[1] = 0; if has_ssd {
radii[3] = 0; radii[1] = 0;
} radii[3] = 0;
elements.extend(self.0.with_program(|p| { }
p.window.render_elements::<R, CosmicWindowRenderElement<R>>( p.window.push_render_elements(
renderer, renderer,
window_loc, window_loc,
scale, scale,
@ -562,8 +556,10 @@ impl CosmicWindow {
scanout_node, scanout_node,
clip, clip,
radii, radii,
&mut |elem| push_above(elem.into()),
Some(&mut |elem| push_below(elem.into())),
) )
})); });
if has_ssd { if has_ssd {
let ssd_loc = location let ssd_loc = location
@ -571,12 +567,11 @@ impl CosmicWindow {
.0 .0
.with_program(|p| p.window.geometry().loc) .with_program(|p| p.window.geometry().loc)
.to_physical_precise_round(scale); .to_physical_precise_round(scale);
elements.extend(AsRenderElements::<R>::render_elements::< self.0
CosmicWindowRenderElement<R>, .push_render_elements(renderer, ssd_loc, scale, alpha, &mut |elem| {
>(&self.0, renderer, ssd_loc, scale, alpha)) push_above(elem.into())
});
} }
elements.into_iter().map(C::from).collect()
} }
pub(crate) fn set_theme(&self, theme: cosmic::Theme) { pub(crate) fn set_theme(&self, theme: cosmic::Theme) {

View file

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

View file

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

View file

@ -9,11 +9,12 @@ use std::{
use cosmic_comp_config::AppearanceConfig; use cosmic_comp_config::AppearanceConfig;
use cosmic_settings_config::shortcuts::action::ResizeDirection; use cosmic_settings_config::shortcuts::action::ResizeDirection;
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smallvec::SmallVec;
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
renderer::element::{ renderer::element::{
AsRenderElements, RenderElement, RenderElement,
utils::{Relocate, RelocateRenderElement, RescaleRenderElement}, utils::{Relocate, RelocateRenderElement, RescaleRenderElement},
}, },
}, },
@ -1443,8 +1444,8 @@ impl FloatingLayout {
renderer: &mut R, renderer: &mut R,
alpha: f32, alpha: f32,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -1454,8 +1455,6 @@ impl FloatingLayout {
let output = self.space.outputs().next().unwrap(); let output = self.space.outputs().next().unwrap();
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
let mut elements = Vec::default();
for elem in self for elem in self
.animations .animations
.iter() .iter()
@ -1470,20 +1469,17 @@ impl FloatingLayout {
.unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha)); .unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha));
let render_location = geometry.loc - elem.geometry().loc.as_local(); let render_location = geometry.loc - elem.geometry().loc.as_local();
elements.extend( elem.push_popup_render_elements(
elem.popup_render_elements( renderer,
renderer, render_location
render_location .as_logical()
.as_logical() .to_physical_precise_round(output_scale),
.to_physical_precise_round(output_scale), output_scale.into(),
output_scale.into(), alpha,
alpha, scanout_node,
scanout_node, push,
),
); );
} }
elements
} }
#[profiling::function] #[profiling::function]
@ -1496,8 +1492,8 @@ impl FloatingLayout {
alpha: f32, alpha: f32,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -1510,8 +1506,7 @@ impl FloatingLayout {
layers.non_exclusive_zone() layers.non_exclusive_zone()
}; };
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
let mut lower_elements = SmallVec::<[_; 4]>::new_const();
let mut elements = Vec::default();
for elem in self for elem in self
.animations .animations
@ -1525,122 +1520,9 @@ impl FloatingLayout {
.get(elem) .get(elem)
.map(|anim| (*anim.previous_geometry(), alpha * anim.alpha())) .map(|anim| (*anim.previous_geometry(), alpha * anim.alpha()))
.unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha)); .unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha));
let render_location = geometry.loc - elem.geometry().loc.as_local(); let render_location = geometry.loc - elem.geometry().loc.as_local();
let mut window_elements = elem.render_elements(
renderer,
render_location
.as_logical()
.to_physical_precise_round(output_scale),
None,
output_scale.into(),
alpha,
None,
scanout_node,
);
window_elements.extend(
elem.shadow_render_element(
renderer,
render_location
.as_logical()
.to_physical_precise_round(output_scale),
None,
output_scale.into(),
1.,
alpha,
),
);
if let Some(anim) = self.animations.get(elem) {
let original_geo = anim.previous_geometry();
geometry = anim.geometry(
output_geometry,
self.space
.element_geometry(elem)
.map(RectExt::as_local)
.unwrap_or(geometry),
elem.floating_tiled.lock().unwrap().as_ref(),
self.gaps(),
);
let buffer_size = elem.geometry().size;
let scale = Scale {
x: geometry.size.w as f64 / buffer_size.w as f64,
y: geometry.size.h as f64 / buffer_size.h as f64,
};
window_elements = window_elements
.into_iter()
.map(|element| match element {
CosmicMappedRenderElement::Stack(elem) => {
CosmicMappedRenderElement::MovingStack({
let rescaled = RescaleRenderElement::from_element(
elem,
original_geo
.loc
.as_logical()
.to_physical_precise_round(output_scale),
scale,
);
RelocateRenderElement::from_element(
rescaled,
(geometry.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
)
})
}
CosmicMappedRenderElement::Window(elem) => {
CosmicMappedRenderElement::MovingWindow({
let rescaled = RescaleRenderElement::from_element(
elem,
original_geo
.loc
.as_logical()
.to_physical_precise_round(output_scale),
scale,
);
RelocateRenderElement::from_element(
rescaled,
(geometry.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
)
})
}
x => x,
})
.collect();
}
if focused == Some(elem) && !elem.is_maximized(false) { if focused == Some(elem) && !elem.is_maximized(false) {
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 */);
window_elements = resize
.render_elements::<CosmicWindowRenderElement<R>>(
renderer,
resize_geometry
.loc
.as_logical()
.to_physical_precise_round(output_scale),
output_scale.into(),
alpha * mode.alpha().unwrap_or(1.0),
)
.into_iter()
.map(CosmicMappedRenderElement::Window)
.chain(window_elements.into_iter())
.collect();
}
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 indicator_thickness > 0 { if indicator_thickness > 0 {
@ -1658,14 +1540,130 @@ impl FloatingLayout {
active_window_hint.blue, active_window_hint.blue,
], ],
); );
window_elements.insert(0, 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())),
);
} }
} }
elements.extend(window_elements); let maybe_map = if let Some(anim) = self.animations.get(elem) {
} let original_geo = anim.previous_geometry();
geometry = anim.geometry(
output_geometry,
self.space
.element_geometry(elem)
.map(RectExt::as_local)
.unwrap_or(geometry),
elem.floating_tiled.lock().unwrap().as_ref(),
self.gaps(),
);
elements let buffer_size = elem.geometry().size;
let scale = Scale {
x: geometry.size.w as f64 / buffer_size.w as f64,
y: geometry.size.h as f64 / buffer_size.h as f64,
};
Some(move |element| match element {
CosmicMappedRenderElement::Stack(elem) => {
CosmicMappedRenderElement::MovingStack({
let rescaled = RescaleRenderElement::from_element(
elem,
original_geo
.loc
.as_logical()
.to_physical_precise_round(output_scale),
scale,
);
RelocateRenderElement::from_element(
rescaled,
(geometry.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
)
})
}
CosmicMappedRenderElement::Window(elem) => {
CosmicMappedRenderElement::MovingWindow({
let rescaled = RescaleRenderElement::from_element(
elem,
original_geo
.loc
.as_logical()
.to_physical_precise_round(output_scale),
scale,
);
RelocateRenderElement::from_element(
rescaled,
(geometry.loc - original_geo.loc)
.as_logical()
.to_physical_precise_round(output_scale),
Relocate::Relative,
)
})
}
x => x,
})
} else {
None
};
let map_anim = |elem| {
if let Some(map) = maybe_map {
map(elem)
} else {
elem
}
};
elem.push_render_elements(
renderer,
render_location
.as_logical()
.to_physical_precise_round(output_scale),
None,
output_scale.into(),
alpha,
None,
scanout_node,
&mut |elem| push(map_anim(elem)),
&mut |elem| lower_elements.push(map_anim(elem)),
);
if let Some(shadow_element) = elem.shadow_render_element(
renderer,
render_location
.as_logical()
.to_physical_precise_round(output_scale),
None,
output_scale.into(),
1.,
alpha,
) {
push(map_anim(shadow_element));
}
for elem in lower_elements.drain(..) {
push(elem);
}
}
} }
pub fn snap_to_corner(&self, mapped: &CosmicMapped, corners: &TiledCorners) { pub fn snap_to_corner(&self, mapped: &CosmicMapped, corners: &TiledCorners) {

View file

@ -6,8 +6,7 @@ use crate::{
element::AsGlowRenderer, element::AsGlowRenderer,
}, },
shell::{ shell::{
CosmicSurface, Direction, FocusResult, MoveResult, OutputNotMapped, OverviewMode, CosmicSurface, Direction, FocusResult, MoveResult, OverviewMode, ResizeMode, Trigger,
ResizeMode, Trigger,
element::{ element::{
CosmicMapped, CosmicMappedRenderElement, CosmicStack, CosmicWindow, CosmicMapped, CosmicMappedRenderElement, CosmicStack, CosmicWindow,
resize_indicator::ResizeIndicator, resize_indicator::ResizeIndicator,
@ -45,12 +44,13 @@ use keyframe::{
ease, ease,
functions::{EaseInOutCubic, Linear}, functions::{EaseInOutCubic, Linear},
}; };
use smallvec::SmallVec;
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
renderer::{ renderer::{
element::{ element::{
AsRenderElements, Id, RenderElement, Id, RenderElement,
utils::{ utils::{
ConstrainAlign, ConstrainScaleBehavior, RescaleRenderElement, ConstrainAlign, ConstrainScaleBehavior, RescaleRenderElement,
constrain_render_elements, constrain_render_elements,
@ -3424,8 +3424,8 @@ impl TilingLayout {
None, None,
None, None,
self.theme.cosmic(), self.theme.cosmic(),
) &mut |_| {},
.0; );
let mut result = None; let mut result = None;
let mut lookup = Some(root.clone()); let mut lookup = Some(root.clone());
@ -4011,8 +4011,8 @@ impl TilingLayout {
indicator_thickness: u8, indicator_thickness: u8,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Result<Vec<CosmicMappedRenderElement<R>>, OutputNotMapped> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -4052,8 +4052,6 @@ impl TilingLayout {
}; };
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let mut elements = Vec::default();
let is_overview = !matches!(overview.0, OverviewMode::None); let is_overview = !matches!(overview.0, OverviewMode::None);
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
.then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone));
@ -4065,7 +4063,7 @@ impl TilingLayout {
// all gone windows and fade them out // all gone windows and fade them out
let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() { let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() {
let (geometries, _) = if let Some(transition) = draw_groups { let geometries = if let Some(transition) = draw_groups {
Some(geometries_for_groupview( Some(geometries_for_groupview(
reference_tree, reference_tree,
&mut *renderer, &mut *renderer,
@ -4080,14 +4078,14 @@ impl TilingLayout {
swap_desc.clone(), swap_desc.clone(),
overview.1.as_ref().and_then(|(_, tree)| *tree), overview.1.as_ref().and_then(|(_, tree)| *tree),
theme, theme,
&mut |_elem| {},
)) ))
} else { } else {
None None
} };
.unzip();
// all old windows we want to fade out // all old windows we want to fade out
elements.extend(render_old_tree_windows( render_old_tree_windows(
reference_tree, reference_tree,
target_tree, target_tree,
renderer, renderer,
@ -4098,14 +4096,16 @@ impl TilingLayout {
swap_desc.is_some(), swap_desc.is_some(),
theme, theme,
scanout_node, scanout_node,
)); push,
);
geometries geometries
} else { } else {
None None
}; };
let (geometries, group_elements) = if let Some(transition) = draw_groups { let mut group_elements = SmallVec::<[_; 4]>::new_const();
let geometries = if let Some(transition) = draw_groups {
Some(geometries_for_groupview( Some(geometries_for_groupview(
target_tree, target_tree,
&mut *renderer, &mut *renderer,
@ -4119,14 +4119,14 @@ impl TilingLayout {
swap_desc.clone(), swap_desc.clone(),
overview.1.as_ref().and_then(|(_, tree)| *tree), overview.1.as_ref().and_then(|(_, tree)| *tree),
theme, theme,
&mut |elem| group_elements.push(elem),
)) ))
} else { } else {
None None
} };
.unzip();
// all alive windows // all alive windows
elements.extend(render_new_tree_windows( render_new_tree_windows(
target_tree, target_tree,
reference_tree, reference_tree,
renderer, renderer,
@ -4155,14 +4155,13 @@ impl TilingLayout {
&self.backdrop_id, &self.backdrop_id,
theme, theme,
scanout_node, scanout_node,
)); push,
);
// tiling hints // tiling hints
if let Some(group_elements) = group_elements { for elem in group_elements.into_iter() {
elements.extend(group_elements); push(elem);
} }
Ok(elements)
} }
#[profiling::function] #[profiling::function]
@ -4174,8 +4173,8 @@ impl TilingLayout {
overview: (OverviewMode, Option<(SwapIndicator, Option<&Tree<Data>>)>), overview: (OverviewMode, Option<(SwapIndicator, Option<&Tree<Data>>)>),
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Result<Vec<CosmicMappedRenderElement<R>>, OutputNotMapped> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -4207,8 +4206,6 @@ impl TilingLayout {
}; };
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let mut elements = Vec::default();
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
.then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone));
let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() {
@ -4219,7 +4216,7 @@ impl TilingLayout {
// all gone windows and fade them out // all gone windows and fade them out
let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() { let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() {
let (geometries, _) = if let Some(transition) = draw_groups { let geometries = if let Some(transition) = draw_groups {
Some(geometries_for_groupview( Some(geometries_for_groupview(
reference_tree, reference_tree,
&mut *renderer, &mut *renderer,
@ -4234,14 +4231,14 @@ impl TilingLayout {
swap_desc.clone(), swap_desc.clone(),
overview.1.as_ref().and_then(|(_, tree)| *tree), overview.1.as_ref().and_then(|(_, tree)| *tree),
theme, theme,
&mut |_| {},
)) ))
} else { } else {
None None
} };
.unzip();
// all old windows we want to fade out // all old windows we want to fade out
elements.extend(render_old_tree_popups( render_old_tree_popups(
reference_tree, reference_tree,
target_tree, target_tree,
renderer, renderer,
@ -4250,14 +4247,15 @@ impl TilingLayout {
percentage, percentage,
swap_desc.is_some(), swap_desc.is_some(),
scanout_node, scanout_node,
)); push,
);
geometries geometries
} else { } else {
None None
}; };
let (geometries, _) = if let Some(transition) = draw_groups { let geometries = if let Some(transition) = draw_groups {
Some(geometries_for_groupview( Some(geometries_for_groupview(
target_tree, target_tree,
&mut *renderer, &mut *renderer,
@ -4271,14 +4269,14 @@ impl TilingLayout {
swap_desc.clone(), swap_desc.clone(),
overview.1.as_ref().and_then(|(_, tree)| *tree), overview.1.as_ref().and_then(|(_, tree)| *tree),
theme, theme,
&mut |_| {},
)) ))
} else { } else {
None None
} };
.unzip();
// all alive windows // all alive windows
elements.extend(render_new_tree_popups( render_new_tree_popups(
target_tree, target_tree,
reference_tree, reference_tree,
renderer, renderer,
@ -4290,9 +4288,8 @@ impl TilingLayout {
overview, overview,
swap_desc.clone(), swap_desc.clone(),
scanout_node, scanout_node,
)); push,
);
Ok(elements)
} }
fn gaps(&self) -> (i32, i32) { fn gaps(&self) -> (i32, i32) {
@ -4347,10 +4344,8 @@ fn geometries_for_groupview<'a, R>(
swap_desc: Option<NodeDesc>, swap_desc: Option<NodeDesc>,
swap_tree: Option<&Tree<Data>>, swap_tree: Option<&Tree<Data>>,
_theme: &cosmic::theme::CosmicTheme, _theme: &cosmic::theme::CosmicTheme,
) -> ( push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
HashMap<NodeId, Rectangle<i32, Local>>, ) -> HashMap<NodeId, Rectangle<i32, Local>>
Vec<CosmicMappedRenderElement<R>>,
)
where where
R: AsGlowRenderer + 'a, R: AsGlowRenderer + 'a,
R::TextureId: 'static, R::TextureId: 'static,
@ -4373,11 +4368,18 @@ where
// push bogos value, that will get ignored anyway // push bogos value, that will get ignored anyway
stack.push((Rectangle::from_size((320, 240).into()), 0)); stack.push((Rectangle::from_size((320, 240).into()), 0));
} }
if root.is_some() {
let has_root = root.is_some();
if has_root {
stack.push((non_exclusive_zone, 0)); stack.push((non_exclusive_zone, 0));
} }
let mut elements = Vec::new(); let mut push = |elem| {
if has_root {
push(elem)
}
};
let mut geometries: HashMap<NodeId, Rectangle<i32, Local>> = HashMap::new(); let mut geometries: HashMap<NodeId, Rectangle<i32, Local>> = HashMap::new();
let alpha = alpha * transition; let alpha = alpha * transition;
@ -4532,7 +4534,7 @@ where
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
if (render_potential_group || render_active_child) && Some(&node_id) != root if (render_potential_group || render_active_child) && Some(&node_id) != root
{ {
elements.push( push(
IndicatorShader::element( IndicatorShader::element(
*renderer, *renderer,
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
@ -4550,7 +4552,7 @@ where
&& pill_indicator.is_some() && pill_indicator.is_some()
&& Some(&node_id) != root && Some(&node_id) != root
{ {
elements.push( push(
IndicatorShader::element( IndicatorShader::element(
*renderer, *renderer,
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
@ -4614,7 +4616,7 @@ where
}; };
if draw_outline { if draw_outline {
elements.push( push(
IndicatorShader::element( IndicatorShader::element(
*renderer, *renderer,
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
@ -4675,7 +4677,7 @@ where
}; };
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
elements.push( push(
BackdropShader::element( BackdropShader::element(
*renderer, *renderer,
backdrop_id.clone(), backdrop_id.clone(),
@ -4693,7 +4695,7 @@ where
if matches!(swap_desc, Some(ref desc) if desc.node == node_id) { if matches!(swap_desc, Some(ref desc) if desc.node == node_id) {
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
elements.push( push(
BackdropShader::element( BackdropShader::element(
*renderer, *renderer,
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
@ -4778,7 +4780,7 @@ where
.unwrap_or(false) .unwrap_or(false)
{ {
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
elements.push( push(
BackdropShader::element( BackdropShader::element(
*renderer, *renderer,
backdrop_id.clone(), backdrop_id.clone(),
@ -4820,7 +4822,7 @@ where
.unwrap_or(false) .unwrap_or(false)
{ {
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
elements.push( push(
BackdropShader::element( BackdropShader::element(
*renderer, *renderer,
backdrop_id.clone(), backdrop_id.clone(),
@ -4851,7 +4853,7 @@ where
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
if render_potential_group { if render_potential_group {
elements.push( push(
IndicatorShader::element( IndicatorShader::element(
*renderer, *renderer,
Key::Window(Usage::PotentialGroupIndicator, mapped.key()), Key::Window(Usage::PotentialGroupIndicator, mapped.key()),
@ -4891,7 +4893,7 @@ where
geo.loc += (WINDOW_BACKDROP_BORDER, WINDOW_BACKDROP_BORDER).into(); geo.loc += (WINDOW_BACKDROP_BORDER, WINDOW_BACKDROP_BORDER).into();
geo.size -= geo.size -=
(WINDOW_BACKDROP_BORDER * 2, WINDOW_BACKDROP_BORDER * 2).into(); (WINDOW_BACKDROP_BORDER * 2, WINDOW_BACKDROP_BORDER * 2).into();
elements.push( push(
BackdropShader::element( BackdropShader::element(
*renderer, *renderer,
Key::Window(Usage::OverviewBackdrop, mapped.key()), Key::Window(Usage::OverviewBackdrop, mapped.key()),
@ -4948,7 +4950,7 @@ where
if let Some(renderer) = renderer.as_mut() { if let Some(renderer) = renderer.as_mut() {
geo.loc += (WINDOW_BACKDROP_BORDER, WINDOW_BACKDROP_BORDER).into(); geo.loc += (WINDOW_BACKDROP_BORDER, WINDOW_BACKDROP_BORDER).into();
geo.size -= (WINDOW_BACKDROP_BORDER * 2, WINDOW_BACKDROP_BORDER * 2).into(); geo.size -= (WINDOW_BACKDROP_BORDER * 2, WINDOW_BACKDROP_BORDER * 2).into();
elements.push( push(
BackdropShader::element( BackdropShader::element(
*renderer, *renderer,
id.clone(), id.clone(),
@ -4967,11 +4969,7 @@ where
} }
} }
if root.is_none() { geometries
elements.clear();
}
(geometries, elements)
} }
fn render_old_tree_popups<R>( fn render_old_tree_popups<R>(
@ -4983,16 +4981,14 @@ fn render_old_tree_popups<R>(
percentage: f32, percentage: f32,
is_swap_mode: bool, is_swap_mode: bool,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
CosmicWindowRenderElement<R>: RenderElement<R>, CosmicWindowRenderElement<R>: RenderElement<R>,
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
{ {
let mut elements = Vec::default();
render_old_tree( render_old_tree(
reference_tree, reference_tree,
target_tree, target_tree,
@ -5001,20 +4997,16 @@ where
percentage, percentage,
is_swap_mode, is_swap_mode,
|mapped, elem_geometry, geo, alpha, _| { |mapped, elem_geometry, geo, alpha, _| {
elements.extend( mapped.push_popup_render_elements(
mapped.popup_render_elements::<R, CosmicMappedRenderElement<R>>( renderer,
renderer, geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
geo.loc.as_logical().to_physical_precise_round(output_scale) Scale::from(output_scale),
- elem_geometry.loc, alpha,
Scale::from(output_scale), scanout_node,
alpha, push,
scanout_node, )
),
);
}, },
); )
elements
} }
fn render_old_tree_windows<R>( fn render_old_tree_windows<R>(
@ -5028,8 +5020,8 @@ fn render_old_tree_windows<R>(
is_swap_mode: bool, is_swap_mode: bool,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -5037,8 +5029,35 @@ where
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
{ {
let window_hint = crate::theme::active_window_hint(theme); let window_hint = crate::theme::active_window_hint(theme);
let mut elements = Vec::default(); let mut lower_elements = Vec::default();
let mut shadow_elements = Vec::default(); let mut shadow_elements = SmallVec::<[_; 4]>::new_const();
let window_map =
|elem, geo: Rectangle<i32, Local>, elem_geometry: Rectangle<i32, Physical>| match elem {
CosmicMappedRenderElement::Stack(elem) => constrain_render_elements(
std::iter::once(elem),
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
geo.as_logical().to_physical_precise_round(output_scale),
elem_geometry,
ConstrainScaleBehavior::Stretch,
ConstrainAlign::CENTER,
output_scale,
)
.next()
.map(CosmicMappedRenderElement::TiledStack),
CosmicMappedRenderElement::Window(elem) => constrain_render_elements(
std::iter::once(elem),
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
geo.as_logical().to_physical_precise_round(output_scale),
elem_geometry,
ConstrainScaleBehavior::Stretch,
ConstrainAlign::CENTER,
output_scale,
)
.next()
.map(CosmicMappedRenderElement::TiledWindow),
x => Some(x),
};
render_old_tree( render_old_tree(
reference_tree, reference_tree,
@ -5048,57 +5067,9 @@ where
percentage, percentage,
is_swap_mode, is_swap_mode,
|mapped, elem_geometry, geo, alpha, is_minimizing| { |mapped, elem_geometry, geo, alpha, is_minimizing| {
shadow_elements.extend(mapped.shadow_render_element(
renderer,
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
Some(geo.size.as_logical()),
Scale::from(output_scale),
1.,
alpha,
));
let window_elements = mapped.render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
Some(geo.size.as_logical()),
Scale::from(output_scale),
alpha,
None,
scanout_node,
);
elements.extend(window_elements.into_iter().flat_map(|element| {
match element {
CosmicMappedRenderElement::Stack(elem) => constrain_render_elements(
std::iter::once(elem),
geo.loc.as_logical().to_physical_precise_round(output_scale)
- elem_geometry.loc,
geo.as_logical().to_physical_precise_round(output_scale),
elem_geometry,
ConstrainScaleBehavior::Stretch,
ConstrainAlign::CENTER,
output_scale,
)
.next()
.map(CosmicMappedRenderElement::TiledStack),
CosmicMappedRenderElement::Window(elem) => constrain_render_elements(
std::iter::once(elem),
geo.loc.as_logical().to_physical_precise_round(output_scale)
- elem_geometry.loc,
geo.as_logical().to_physical_precise_round(output_scale),
elem_geometry,
ConstrainScaleBehavior::Stretch,
ConstrainAlign::CENTER,
output_scale,
)
.next()
.map(CosmicMappedRenderElement::TiledWindow),
x => Some(x),
}
}));
let radius = mapped.corner_radius(geo.size.as_logical(), indicator_thickness); let radius = mapped.corner_radius(geo.size.as_logical(), indicator_thickness);
if is_minimizing && indicator_thickness > 0 { if is_minimizing && indicator_thickness > 0 {
elements.push(CosmicMappedRenderElement::FocusIndicator( push(CosmicMappedRenderElement::FocusIndicator(
IndicatorShader::focus_element( IndicatorShader::focus_element(
renderer, renderer,
Key::Window(Usage::FocusIndicator, mapped.clone().key()), Key::Window(Usage::FocusIndicator, mapped.clone().key()),
@ -5111,10 +5082,44 @@ where
), ),
)); ));
} }
mapped.push_render_elements(
renderer,
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
Some(geo.size.as_logical()),
Scale::from(output_scale),
alpha,
None,
scanout_node,
&mut |elem| {
if let Some(elem) = window_map(elem, geo, elem_geometry) {
push(elem);
}
},
&mut |elem| {
if let Some(elem) = window_map(elem, geo, elem_geometry) {
lower_elements.push(elem);
}
},
);
shadow_elements.extend(mapped.shadow_render_element(
renderer,
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
Some(geo.size.as_logical()),
Scale::from(output_scale),
1.,
alpha,
));
}, },
); );
shadow_elements.into_iter().chain(elements).collect() for elem in shadow_elements {
push(elem);
}
for elem in lower_elements {
push(elem);
}
} }
fn render_old_tree( fn render_old_tree(
@ -5210,15 +5215,14 @@ fn render_new_tree_popups<R>(
overview: (OverviewMode, Option<(SwapIndicator, Option<&Tree<Data>>)>), overview: (OverviewMode, Option<(SwapIndicator, Option<&Tree<Data>>)>),
swap_desc: Option<NodeDesc>, swap_desc: Option<NodeDesc>,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
CosmicWindowRenderElement<R>: RenderElement<R>, CosmicWindowRenderElement<R>: RenderElement<R>,
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
{ {
let mut popup_elements = Vec::new();
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
let is_active_output = seat let is_active_output = seat
@ -5241,21 +5245,18 @@ where
if let Data::Mapped { mapped, .. } = data { if let Data::Mapped { mapped, .. } = data {
let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale); let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
popup_elements.extend( mapped.push_popup_render_elements(
mapped.popup_render_elements::<R, CosmicMappedRenderElement<R>>( renderer,
renderer, geo.loc.as_logical().to_physical_precise_round(output_scale)
geo.loc.as_logical().to_physical_precise_round(output_scale) - elem_geometry.loc,
- elem_geometry.loc, Scale::from(output_scale),
Scale::from(output_scale), alpha,
alpha, scanout_node,
scanout_node, push,
),
); );
} }
}, },
); );
popup_elements
} }
fn render_new_tree_windows<R>( fn render_new_tree_windows<R>(
@ -5278,8 +5279,8 @@ fn render_new_tree_windows<R>(
backdrop_id: &Id, backdrop_id: &Id,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>> push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -5319,14 +5320,18 @@ where
.map(|seat| &seat.active_output() == output) .map(|seat| &seat.active_output() == output)
.unwrap_or(false); .unwrap_or(false);
let mut animating_window_elements = Vec::new(); let mut animating_window_upper_elements = Vec::new();
let mut window_elements = Vec::new(); let mut animating_window_lower_elements = Vec::new();
let mut animating_shadow_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
let mut window_upper_elements = Vec::new();
let mut window_lower_elements = Vec::new();
let mut shadow_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
let mut group_backdrop = None; let mut group_backdrop = None;
let mut indicators = Vec::new(); let mut indicators = SmallVec::<[CosmicMappedRenderElement<R>; 2]>::new_const();
let mut resize_elements = None; let mut resize_element = None;
let mut swap_elements = Vec::new(); let mut swap_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
let mut shadow_elements = Vec::new();
let output_geo = output.geometry(); let output_geo = output.geometry();
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
@ -5339,7 +5344,7 @@ where
// render placeholder, if we are swapping to an empty workspace // render placeholder, if we are swapping to an empty workspace
if target_tree.root_node_id().is_none() && swap_desc.is_some() { if target_tree.root_node_id().is_none() && swap_desc.is_some() {
window_elements.push( window_upper_elements.push(
BackdropShader::element( BackdropShader::element(
renderer, renderer,
backdrop_id.clone(), backdrop_id.clone(),
@ -5394,22 +5399,19 @@ where
let render_loc = let render_loc =
(swap_geo.loc.as_logical() - window_geo.loc).to_physical_precise_round(output_scale); (swap_geo.loc.as_logical() - window_geo.loc).to_physical_precise_round(output_scale);
swap_elements.extend( window.push_render_elements(
window renderer,
.render_elements( render_loc,
renderer, output_scale.into(),
render_loc, 1.0,
output_scale.into(), None,
1.0, scanout_node,
None, false,
scanout_node, [0, 0, 0, 0],
false, &mut |elem| {
[0; 4], swap_elements.push(CosmicMappedRenderElement::GrabbedWindow(
) RescaleRenderElement::from_element(
.into_iter() elem.into(),
.map(|window| {
CosmicMappedRenderElement::GrabbedWindow(RescaleRenderElement::from_element(
window,
swap_geo swap_geo
.loc .loc
.as_logical() .as_logical()
@ -5420,9 +5422,11 @@ where
swap_factor(window_geo.size), swap_factor(window_geo.size),
transition.unwrap_or(1.0), transition.unwrap_or(1.0),
), ),
)) ),
}), ));
) },
None,
);
} }
// render actual tree nodes // render actual tree nodes
@ -5538,15 +5542,12 @@ where
{ {
swap.resize(geo.size.as_logical()); swap.resize(geo.size.as_logical());
swap.output_enter(output, output_geo.as_logical()); swap.output_enter(output, output_geo.as_logical());
swap_elements.extend( swap.push_render_elements(
swap.render_elements::<CosmicWindowRenderElement<R>>( 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()),
)
.into_iter()
.map(CosmicMappedRenderElement::from),
); );
} }
} }
@ -5572,17 +5573,14 @@ where
}) { }) {
resize.force_update(); resize.force_update();
} }
resize_elements = Some( resize.push_render_elements(
resize renderer,
.render_elements::<CosmicWindowRenderElement<R>>( geo.loc.as_logical().to_physical_precise_round(output_scale),
renderer, output_scale.into(),
geo.loc.as_logical().to_physical_precise_round(output_scale), alpha * mode.alpha().unwrap_or(1.0),
output_scale.into(), &mut |elem| {
alpha * mode.alpha().unwrap_or(1.0), resize_element = Some(elem.into());
) },
.into_iter()
.map(CosmicMappedRenderElement::from)
.collect::<Vec<_>>(),
); );
} }
} }
@ -5608,52 +5606,6 @@ where
scale.x.min(scale.y), scale.x.min(scale.y),
alpha, alpha,
); );
let mut elements = mapped.render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
//original_location,
geo.loc.as_logical().to_physical_precise_round(output_scale)
- elem_geometry.loc,
max_size,
Scale::from(output_scale),
alpha,
None,
scanout_node,
);
if swap_desc
.as_ref()
.filter(|swap_desc| swap_desc.node == node_id)
.and_then(|swap_desc| swap_desc.stack_window.as_ref())
.zip(focused.as_ref())
.map(|(stack_window, focused_id)| {
target_tree
.get(focused_id)
.ok()
.map(|focused| match focused.data() {
Data::Mapped { mapped, .. } => mapped
.stack_ref()
.map(|stack| &stack.active() == stack_window)
.unwrap_or(false),
_ => false,
})
.unwrap_or(false)
})
.unwrap_or(false)
{
let mut active_geo = mapped.active_window_geometry().as_local();
active_geo.loc += geo.loc - mapped.geometry().loc.as_local();
elements.insert(
0,
CosmicMappedRenderElement::Overlay(BackdropShader::element(
renderer,
Key::Window(Usage::Overlay, mapped.key()),
active_geo,
0.0,
0.3,
group_color,
)),
)
}
let (behavior, align) = if is_overview { let (behavior, align) = if is_overview {
(ConstrainScaleBehavior::Fit, ConstrainAlign::CENTER) (ConstrainScaleBehavior::Fit, ConstrainAlign::CENTER)
@ -5663,7 +5615,7 @@ where
(ConstrainScaleBehavior::CutOff, ConstrainAlign::TOP_LEFT) (ConstrainScaleBehavior::CutOff, ConstrainAlign::TOP_LEFT)
}; };
let elements = elements.into_iter().flat_map(|element| match element { let map_elem = |element| match element {
CosmicMappedRenderElement::Stack(elem) => constrain_render_elements( CosmicMappedRenderElement::Stack(elem) => constrain_render_elements(
std::iter::once(elem), std::iter::once(elem),
geo.loc.as_logical().to_physical_precise_round(output_scale) geo.loc.as_logical().to_physical_precise_round(output_scale)
@ -5701,7 +5653,66 @@ where
.next() .next()
.map(CosmicMappedRenderElement::TiledOverlay), .map(CosmicMappedRenderElement::TiledOverlay),
x => Some(x), x => Some(x),
}); };
let mut upper_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
let mut lower_elements = SmallVec::<[CosmicMappedRenderElement<R>; 4]>::new_const();
mapped.push_render_elements(
renderer,
//original_location,
geo.loc.as_logical().to_physical_precise_round(output_scale)
- elem_geometry.loc,
max_size,
Scale::from(output_scale),
alpha,
None,
scanout_node,
&mut |elem| {
if let Some(elem) = map_elem(elem) {
upper_elements.push(elem)
}
},
&mut |elem| {
if let Some(elem) = map_elem(elem) {
lower_elements.push(elem)
}
},
);
if swap_desc
.as_ref()
.filter(|swap_desc| swap_desc.node == node_id)
.and_then(|swap_desc| swap_desc.stack_window.as_ref())
.zip(focused.as_ref())
.map(|(stack_window, focused_id)| {
target_tree
.get(focused_id)
.ok()
.map(|focused| match focused.data() {
Data::Mapped { mapped, .. } => mapped
.stack_ref()
.map(|stack| &stack.active() == stack_window)
.unwrap_or(false),
_ => false,
})
.unwrap_or(false)
})
.unwrap_or(false)
{
let mut active_geo = mapped.active_window_geometry().as_local();
active_geo.loc += geo.loc - mapped.geometry().loc.as_local();
upper_elements.insert(
0,
CosmicMappedRenderElement::Overlay(BackdropShader::element(
renderer,
Key::Window(Usage::Overlay, mapped.key()),
active_geo,
0.0,
0.3,
group_color,
)),
)
}
if swap_desc if swap_desc
.as_ref() .as_ref()
@ -5714,30 +5725,36 @@ where
}) })
.unwrap_or(false) .unwrap_or(false)
{ {
swap_elements.extend(upper_elements);
swap_elements.extend(shadow_element); swap_elements.extend(shadow_element);
swap_elements.extend(elements); swap_elements.extend(lower_elements);
} else if animating {
animating_window_upper_elements.extend(upper_elements);
animating_shadow_elements.extend(shadow_element);
animating_window_lower_elements.extend(lower_elements);
} else { } else {
window_upper_elements.extend(upper_elements);
shadow_elements.extend(shadow_element); shadow_elements.extend(shadow_element);
if animating { window_lower_elements.extend(lower_elements);
animating_window_elements.extend(elements);
} else {
window_elements.extend(elements);
}
} }
} }
}, },
); );
resize_elements for elem in resize_element
.into_iter() .into_iter()
.flatten()
.chain(swap_elements) .chain(swap_elements)
.chain(indicators) .chain(indicators)
.chain(window_elements) .chain(window_upper_elements)
.chain(animating_window_elements)
.chain(shadow_elements) .chain(shadow_elements)
.chain(window_lower_elements)
.chain(animating_window_upper_elements)
.chain(animating_shadow_elements)
.chain(animating_window_lower_elements)
.chain(group_backdrop.into_iter().map(Into::into)) .chain(group_backdrop.into_iter().map(Into::into))
.collect() {
push(elem);
}
} }
fn render_new_tree( fn render_new_tree(

View file

@ -1,3 +1,4 @@
use crate::backend::render::wayland::SurfaceRenderElement;
use crate::shell::focus::FocusTarget; use crate::shell::focus::FocusTarget;
use crate::shell::layout::tiling::RestoreTilingState; use crate::shell::layout::tiling::RestoreTilingState;
use crate::wayland::handlers::xdg_activation::ActivationContext; use crate::wayland::handlers::xdg_activation::ActivationContext;
@ -28,6 +29,7 @@ use cosmic_protocols::workspace::v2::server::zcosmic_workspace_handle_v2::Tiling
use id_tree::Tree; use id_tree::Tree;
use indexmap::IndexSet; use indexmap::IndexSet;
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smallvec::SmallVec;
use smithay::backend::drm::DrmNode; use smithay::backend::drm::DrmNode;
use smithay::backend::renderer::element::Kind; use smithay::backend::renderer::element::Kind;
use smithay::output::WeakOutput; use smithay::output::WeakOutput;
@ -35,8 +37,7 @@ use smithay::utils::user_data::UserDataMap;
use smithay::{ use smithay::{
backend::renderer::{ backend::renderer::{
element::{ element::{
Element, Id, RenderElement, surface::WaylandSurfaceRenderElement, Element, Id, RenderElement, texture::TextureRenderElement, utils::RescaleRenderElement,
texture::TextureRenderElement, utils::RescaleRenderElement,
}, },
gles::GlesTexture, gles::GlesTexture,
glow::GlowRenderer, glow::GlowRenderer,
@ -1622,8 +1623,8 @@ impl Workspace {
indicator_thickness: u8, indicator_thickness: u8,
theme: &CosmicTheme, theme: &CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped> push: &mut dyn FnMut(WorkspaceRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -1631,80 +1632,83 @@ impl Workspace {
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let mut elements = Vec::default();
let output_scale = self.output.current_scale().fractional_scale(); let output_scale = self.output.current_scale().fractional_scale();
let zone = { let zone = {
let layer_map = layer_map_for_output(&self.output); let layer_map = layer_map_for_output(&self.output);
layer_map.non_exclusive_zone().as_local() layer_map.non_exclusive_zone().as_local()
}; };
let focused = self.focus_stack.get(last_active_seat).last().cloned(); let focused = self.focus_stack.get(last_active_seat).last().cloned();
let fullscreen_focused = matches!(focused, Some(FocusTarget::Fullscreen(_)));
let render_fullscreen = |fullscreen: &FullscreenSurface, let mut fullscreen_elements = SmallVec::<[WorkspaceRenderElement<R>; 2]>::new_const();
renderer: &mut R, let mut render_fullscreen =
output_scale: f64| |fullscreen: &FullscreenSurface, renderer: &mut R, output_scale: f64| {
-> Vec<WorkspaceRenderElement<R>> { let fullscreen_geo = self.fullscreen_geometry_for(fullscreen);
let fullscreen_geo = self.fullscreen_geometry_for(fullscreen); let previous_geo = fullscreen
let previous_geo = fullscreen .previous_geometry
.previous_geometry .as_ref()
.as_ref() .unwrap_or(&fullscreen_geo);
.unwrap_or(&fullscreen_geo);
let (target_geo, alpha) = match (fullscreen.start_at, fullscreen.ended_at) { let (target_geo, alpha) = match (fullscreen.start_at, fullscreen.ended_at) {
(Some(started), _) => { (Some(started), _) => {
let duration = Instant::now().duration_since(started).as_secs_f64() let duration = Instant::now().duration_since(started).as_secs_f64()
/ FULLSCREEN_ANIMATION_DURATION.as_secs_f64(); / FULLSCREEN_ANIMATION_DURATION.as_secs_f64();
( (
ease( ease(
EaseInOutCubic, EaseInOutCubic,
EaseRectangle(*previous_geo), EaseRectangle(*previous_geo),
EaseRectangle(fullscreen_geo), EaseRectangle(fullscreen_geo),
duration, duration,
)
.0,
ease(EaseInOutCubic, 0.0, 1.0, duration),
) )
.0, }
ease(EaseInOutCubic, 0.0, 1.0, duration), (_, Some(ended)) => {
) let duration = Instant::now().duration_since(ended).as_secs_f64()
} / FULLSCREEN_ANIMATION_DURATION.as_secs_f64();
(_, Some(ended)) => { (
let duration = Instant::now().duration_since(ended).as_secs_f64() ease(
/ FULLSCREEN_ANIMATION_DURATION.as_secs_f64(); EaseInOutCubic,
( EaseRectangle(fullscreen_geo),
ease( EaseRectangle(*previous_geo),
EaseInOutCubic, duration,
EaseRectangle(fullscreen_geo), )
EaseRectangle(*previous_geo), .0,
duration, ease(EaseInOutCubic, 1.0, 0.0, duration),
) )
.0, }
ease(EaseInOutCubic, 1.0, 0.0, duration), (None, None) => (fullscreen_geo, 1.0),
) };
}
(None, None) => (fullscreen_geo, 1.0),
};
let render_loc = target_geo let render_loc = target_geo
.loc .loc
.as_logical() .as_logical()
.to_physical_precise_round(output_scale); .to_physical_precise_round(output_scale);
// Only rescale geometry when animating // Only rescale geometry when animating
let animation_rescale = |elem| { let animation_rescale = |elem| {
if fullscreen.is_animating() { if fullscreen.is_animating() {
let fullscreen_geo = fullscreen.surface.0.geometry(); let fullscreen_geo = fullscreen.surface.0.geometry();
let scale = Scale { let scale = Scale {
x: target_geo.size.w as f64 / fullscreen_geo.size.w as f64, x: target_geo.size.w as f64 / fullscreen_geo.size.w as f64,
y: target_geo.size.h as f64 / fullscreen_geo.size.h as f64, y: target_geo.size.h as f64 / fullscreen_geo.size.h as f64,
}; };
RescaleRenderElement::from_element(elem, render_loc, scale).into() RescaleRenderElement::from_element(elem, render_loc, scale).into()
} else { } else {
Into::<WorkspaceRenderElement<_>>::into(elem) Into::<WorkspaceRenderElement<_>>::into(elem)
} }
}; };
fullscreen let mut fullscreen_push = |elem: SurfaceRenderElement<R>| {
.surface if fullscreen_focused {
.render_elements::<R, CosmicWindowRenderElement<R>>( push(animation_rescale(elem.into()))
} else {
fullscreen_elements.push(animation_rescale(elem.into()))
}
};
fullscreen.surface.push_render_elements(
renderer, renderer,
render_loc, render_loc,
output_scale.into(), output_scale.into(),
@ -1712,30 +1716,24 @@ impl Workspace {
Some(true), Some(true),
scanout_node, scanout_node,
false, false,
[0; 4], [0, 0, 0, 0],
) &mut fullscreen_push,
.into_iter() None,
.map(animation_rescale) );
.collect::<Vec<_>>() };
};
let top_fullscreen = self.get_fullscreen(last_active_seat); let top_fullscreen = self.get_fullscreen(last_active_seat);
let mut fullscreen_elements: Vec<WorkspaceRenderElement<R>> = Vec::new();
if let Some(fs) = top_fullscreen { if let Some(fs) = top_fullscreen {
fullscreen_elements.extend(render_fullscreen(fs, renderer, output_scale)); render_fullscreen(fs, renderer, output_scale)
} }
// Also render any animating (entering/exiting) fullscreens // Also render any animating (entering/exiting) fullscreens
for fs in self.fullscreen_surfaces.iter().filter(|f| f.is_animating()) { for fs in self.fullscreen_surfaces.iter().filter(|f| f.is_animating()) {
if top_fullscreen.is_none_or(|top| top.surface != fs.surface) { if top_fullscreen.is_none_or(|top| top.surface != fs.surface) {
fullscreen_elements.extend(render_fullscreen(fs, renderer, output_scale)); render_fullscreen(fs, renderer, output_scale);
}; };
} }
if matches!(focused, Some(FocusTarget::Fullscreen(_))) {
elements.append(&mut fullscreen_elements);
}
let any_fullscreen_animating = self let any_fullscreen_animating = self
.fullscreen_surfaces .fullscreen_surfaces
.iter() .iter()
@ -1766,29 +1764,21 @@ impl Workspace {
OverviewMode::None => 1.0, OverviewMode::None => 1.0,
}; };
elements.extend( self.floating_layer.render(
self.floating_layer renderer,
.render::<R>( focused.as_ref().and_then(|target| {
renderer, if let FocusTarget::Window(mapped) = target {
render_focus Some(mapped)
.then(|| { } else {
focused.as_ref().and_then(|target| { None
if let FocusTarget::Window(mapped) = target { }
Some(mapped) }),
} else { resize_indicator.clone(),
None indicator_thickness,
} alpha,
}) theme,
}) scanout_node,
.flatten(), &mut |elem| push(elem.into()),
resize_indicator.clone(),
indicator_thickness,
alpha,
theme,
scanout_node,
)
.into_iter()
.map(WorkspaceRenderElement::from),
); );
let alpha = match &overview.0 { let alpha = match &overview.0 {
@ -1805,24 +1795,20 @@ impl Workspace {
}; };
//tiling surfaces //tiling surfaces
elements.extend( self.tiling_layer.render(
self.tiling_layer renderer,
.render::<R>( render_focus.then_some(last_active_seat),
renderer, zone,
render_focus.then_some(last_active_seat), overview,
zone, resize_indicator,
overview, indicator_thickness,
resize_indicator, theme,
indicator_thickness, scanout_node,
theme, &mut |elem| push(elem.into()),
scanout_node,
)?
.into_iter()
.map(WorkspaceRenderElement::from),
); );
if let Some(alpha) = alpha { if let Some(alpha) = alpha {
elements.push( push(
Into::<CosmicMappedRenderElement<R>>::into(BackdropShader::element( Into::<CosmicMappedRenderElement<R>>::into(BackdropShader::element(
renderer, renderer,
self.backdrop_id.clone(), self.backdrop_id.clone(),
@ -1836,11 +1822,9 @@ impl Workspace {
} }
} }
if !matches!(focused, Some(FocusTarget::Fullscreen(_))) { for elem in fullscreen_elements {
elements.extend(fullscreen_elements.into_iter()); push(elem);
} }
Ok(elements)
} }
#[profiling::function] #[profiling::function]
@ -1852,8 +1836,8 @@ impl Workspace {
overview: (OverviewMode, Option<(SwapIndicator, Option<&Tree<Data>>)>), overview: (OverviewMode, Option<(SwapIndicator, Option<&Tree<Data>>)>),
theme: &CosmicTheme, theme: &CosmicTheme,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped> push: &mut dyn FnMut(WorkspaceRenderElement<R>),
where ) where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
@ -1861,8 +1845,6 @@ impl Workspace {
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let mut elements = Vec::default();
let output_scale = self.output.current_scale().fractional_scale(); let output_scale = self.output.current_scale().fractional_scale();
let zone = { let zone = {
let layer_map = layer_map_for_output(&self.output); let layer_map = layer_map_for_output(&self.output);
@ -1917,18 +1899,13 @@ impl Workspace {
.as_logical() .as_logical()
.to_physical_precise_round(output_scale); .to_physical_precise_round(output_scale);
elements.extend( fullscreen.surface.push_popup_render_elements(
fullscreen renderer,
.surface render_loc,
.popup_render_elements::<R, CosmicWindowRenderElement<R>>( output_scale.into(),
renderer, alpha,
render_loc, scanout_node,
output_scale.into(), &mut |elem| push(WorkspaceRenderElement::FullscreenPopup(elem.into())),
alpha,
scanout_node,
)
.into_iter()
.map(Into::into),
); );
} }
@ -1962,30 +1939,20 @@ impl Workspace {
OverviewMode::None => 1.0, OverviewMode::None => 1.0,
}; };
elements.extend( self.floating_layer
self.floating_layer .render_popups(renderer, alpha, scanout_node, &mut |elem| push(elem.into()));
.render_popups::<R>(renderer, alpha, scanout_node)
.into_iter()
.map(WorkspaceRenderElement::from),
);
//tiling surfaces //tiling surfaces
elements.extend( self.tiling_layer.render_popups(
self.tiling_layer renderer,
.render_popups::<R>( render_focus.then_some(last_active_seat),
renderer, zone,
render_focus.then_some(last_active_seat), overview,
zone, theme,
overview, scanout_node,
theme, &mut |elem| push(elem.into()),
scanout_node,
)?
.into_iter()
.map(WorkspaceRenderElement::from),
); );
} }
Ok(elements)
} }
} }
@ -2006,7 +1973,7 @@ where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: 'static, R::TextureId: 'static,
{ {
OverrideRedirect(WaylandSurfaceRenderElement<R>), OverrideRedirect(SurfaceRenderElement<R>),
Fullscreen(RescaleRenderElement<CosmicWindowRenderElement<R>>), Fullscreen(RescaleRenderElement<CosmicWindowRenderElement<R>>),
FullscreenPopup(CosmicWindowRenderElement<R>), FullscreenPopup(CosmicWindowRenderElement<R>),
Window(CosmicMappedRenderElement<R>), Window(CosmicMappedRenderElement<R>),
@ -2244,13 +2211,13 @@ where
} }
} }
impl<R> From<WaylandSurfaceRenderElement<R>> for WorkspaceRenderElement<R> impl<R> From<SurfaceRenderElement<R>> for WorkspaceRenderElement<R>
where where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: 'static, R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
{ {
fn from(elem: WaylandSurfaceRenderElement<R>) -> Self { fn from(elem: SurfaceRenderElement<R>) -> Self {
WorkspaceRenderElement::OverrideRedirect(elem) WorkspaceRenderElement::OverrideRedirect(elem)
} }
} }

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::AsRenderElements}, backend::renderer::{ImportMem, Renderer, element::memory::MemoryRenderBufferRenderElement},
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{ input::{
Seat, Seat,
@ -192,9 +192,12 @@ impl OutputZoomState {
}); });
} }
fn render<R, C>(&mut self, renderer: &mut R, output: &Output) -> Vec<C> fn render<R>(
where &mut self,
C: From<<IcedElement<ZoomProgram> as AsRenderElements<R>>::RenderElement>, renderer: &mut R,
output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem, R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
@ -208,8 +211,13 @@ impl OutputZoomState {
.to_physical(scale.fractional_scale()) .to_physical(scale.fractional_scale())
.to_i32_round(); .to_i32_round();
self.element self.element.push_render_elements(
.render_elements(renderer, location, scale.fractional_scale().into(), 1.0) renderer,
location,
scale.fractional_scale().into(),
1.0,
push,
)
} }
} }
@ -382,14 +390,16 @@ impl ZoomState {
None None
} }
pub fn render<R, C>(renderer: &mut R, output: &Output) -> Vec<C> pub fn render<R>(
where renderer: &mut R,
C: From<<IcedElement<ZoomProgram> as AsRenderElements<R>>::RenderElement>, output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem, 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();
output_state.lock().unwrap().render(renderer, output) output_state.lock().unwrap().render(renderer, output, push)
} }
} }

View file

@ -35,7 +35,7 @@ use smithay::{
renderer::{ renderer::{
ImportMem, Renderer, ImportMem, Renderer,
element::{ element::{
AsRenderElements, Kind, Kind,
memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement}, memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement},
}, },
}, },
@ -910,21 +910,18 @@ impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
} }
} }
impl<P, R> AsRenderElements<R> for IcedElement<P> impl<P: Program + Send + 'static> IcedElement<P> {
where pub fn push_render_elements<R>(
P: Program + Send + 'static,
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
type RenderElement = MemoryRenderBufferRenderElement<R>;
fn render_elements<C: From<Self::RenderElement>>(
&self, &self,
renderer: &mut R, renderer: &mut R,
location: Point<i32, Physical>, location: Point<i32, Physical>,
mut scale: Scale<f64>, mut scale: Scale<f64>,
alpha: f32, alpha: f32,
) -> Vec<C> { push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
// makes partial borrows easier // makes partial borrows easier
let internal_ref = &mut *internal; let internal_ref = &mut *internal;
@ -1055,11 +1052,10 @@ where
Kind::Unspecified, Kind::Unspecified,
) { ) {
Ok(buffer) => { Ok(buffer) => {
return vec![C::from(buffer)]; push(buffer);
} }
Err(err) => tracing::warn!("What? {:?}", err), Err(err) => tracing::warn!("What? {:?}", err),
} }
} }
Vec::new()
} }
} }

View file

@ -14,7 +14,7 @@ use smithay::{
use tracing::warn; use tracing::warn;
use crate::{ use crate::{
backend::render::{RendererRef, element::AsGlowRenderer, wayland::SurfaceRenderElement}, backend::render::{RendererRef, element::AsGlowRenderer},
shell::element::CosmicSurface, shell::element::CosmicSurface,
state::{State, advertised_node_for_surface}, state::{State, advertised_node_for_surface},
}; };
@ -27,7 +27,8 @@ pub fn screenshot_window(state: &mut State, surface: &CosmicSurface) {
R::Error: Send + Sync + 'static, R::Error: Send + Sync + 'static,
{ {
let bbox = bbox_from_surface_tree(&window.wl_surface().unwrap(), (0, 0)); let bbox = bbox_from_surface_tree(&window.wl_surface().unwrap(), (0, 0));
let elements = window.render_elements::<R, SurfaceRenderElement<R>>( let mut elements = Vec::new();
window.push_render_elements(
renderer, renderer,
(-bbox.loc.x, -bbox.loc.y).into(), (-bbox.loc.x, -bbox.loc.y).into(),
Scale::from(1.0), Scale::from(1.0),
@ -36,6 +37,8 @@ pub fn screenshot_window(state: &mut State, surface: &CosmicSurface) {
None, None,
false, false,
[0; 4], [0; 4],
&mut |elem| elements.push(elem),
None,
); );
// TODO: 10-bit // TODO: 10-bit

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use calloop::LoopHandle; use calloop::LoopHandle;
use smallvec::SmallVec;
use smithay::{ use smithay::{
backend::{ backend::{
allocator::{Buffer, Fourcc, format::get_transparent}, allocator::{Buffer, Fourcc, format::get_transparent},
@ -39,7 +40,8 @@ use tracing::warn;
use crate::{ use crate::{
backend::render::{ backend::render::{
CursorMode, ElementFilter, RendererRef, cursor, CursorMode, ElementFilter, RendererRef,
cursor::{self, CursorRenderElement},
element::{AsGlowRenderer, CosmicElement, DamageElement}, element::{AsGlowRenderer, CosmicElement, DamageElement},
render_workspace, render_workspace,
wayland::SurfaceRenderElement, wayland::SurfaceRenderElement,
@ -591,44 +593,49 @@ pub fn render_window_to_buffer(
if let Some(location) = location { if let Some(location) = location {
if draw_cursor { if draw_cursor {
elements.extend( cursor::draw_cursor(
cursor::draw_cursor( renderer,
renderer, &seat,
&seat, location,
location, 1.0.into(),
1.0.into(), 1.0,
1.0, common.clock.now(),
common.clock.now(), true,
true, &mut |elem, hotspot| {
) elements.push(WindowCaptureElement::CursorElement(
.into_iter() RelocateRenderElement::from_element(
.map(|(elem, hotspot)| { elem,
WindowCaptureElement::CursorElement(RelocateRenderElement::from_element( Point::from((-hotspot.x, -hotspot.y)),
elem, Relocate::Relative,
Point::from((-hotspot.x, -hotspot.y)), ),
Relocate::Relative, ));
)) },
}),
); );
} }
// TODO cosmic-workspaces wants to omit, but metadata cursor capture in portal should // TODO cosmic-workspaces wants to omit, but metadata cursor capture in portal should
// still include dnd surface in window capture buffer? // still include dnd surface in window capture buffer?
if draw_cursor && let Some(dnd_icon) = get_dnd_icon(&seat) { if draw_cursor && let Some(dnd_icon) = get_dnd_icon(&seat) {
elements.extend( cursor::draw_dnd_icon(
cursor::draw_dnd_icon( renderer,
renderer, &dnd_icon.surface,
&dnd_icon.surface, (location + dnd_icon.offset.to_f64()).to_i32_round(),
(location + dnd_icon.offset.to_f64()).to_i32_round(), 1.0,
1.0, &mut |elem| {
) elements.push(
.into_iter() RelocateRenderElement::from_element(
.map(WindowCaptureElement::from), CursorRenderElement::Surface(elem),
Point::new(0, 0),
Relocate::Relative,
)
.into(),
)
},
); );
} }
} }
elements.extend(toplevel.render_elements::<R, WindowCaptureElement<R>>( toplevel.push_render_elements(
renderer, renderer,
(-geometry.loc.x, -geometry.loc.y).into(), (-geometry.loc.x, -geometry.loc.y).into(),
Scale::from(1.0), Scale::from(1.0),
@ -637,7 +644,9 @@ pub fn render_window_to_buffer(
None, None,
false, false,
[0; 4], [0; 4],
)); &mut |elem| elements.push(elem.into()),
None,
);
if let Ok(dmabuf) = get_dmabuf(buffer) { if let Ok(dmabuf) = get_dmabuf(buffer) {
let mut dmabuf_clone = dmabuf.clone(); let mut dmabuf_clone = dmabuf.clone();
@ -803,7 +812,8 @@ pub fn render_cursor_to_buffer(
.collect(); .collect();
dt.damage_output(age, &additional_damage_elements)?; dt.damage_output(age, &additional_damage_elements)?;
let elements = cursor::draw_cursor( let mut elements = SmallVec::<[WindowCaptureElement<R>; 4]>::new_const();
cursor::draw_cursor(
renderer, renderer,
seat, seat,
Point::from((0.0, 0.0)), Point::from((0.0, 0.0)),
@ -811,11 +821,12 @@ pub fn render_cursor_to_buffer(
1.0, 1.0,
common.clock.now(), common.clock.now(),
true, true,
) &mut |elem, _| {
.into_iter() elements.push(
.map(|(elem, _)| RelocateRenderElement::from_element(elem, (0, 0), Relocate::Relative)) RelocateRenderElement::from_element(elem, (0, 0), Relocate::Relative).into(),
.map(WindowCaptureElement::from) )
.collect::<Vec<_>>(); },
);
if let Ok(dmabuf) = get_dmabuf(buffer) { if let Ok(dmabuf) = get_dmabuf(buffer) {
let mut dmabuf_clone = dmabuf.clone(); let mut dmabuf_clone = dmabuf.clone();