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

View file

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

View file

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

View file

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

View file

@ -23,7 +23,7 @@ render_elements! {
Wayland=WaylandSurfaceRenderElement<R>,
}
pub fn render_elements_from_surface_tree<R, E>(
pub fn push_render_elements_from_surface_tree<R>(
renderer: &mut R,
main_surface: &wl_surface::WlSurface,
location: impl Into<Point<i32, Physical>>,
@ -33,17 +33,17 @@ pub fn render_elements_from_surface_tree<R, E>(
should_clip: bool,
radii: [u8; 4],
kind: impl Into<KindEvaluation>,
) -> Vec<E>
where
push_above: &mut dyn FnMut(SurfaceRenderElement<R>),
mut push_below: Option<&mut dyn FnMut(SurfaceRenderElement<R>)>,
) where
R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static,
E: From<SurfaceRenderElement<R>>,
{
let location = location.into().to_f64();
let geometry = geometry.into().to_f64();
let scale = scale.into();
let kind = kind.into();
let mut surfaces: Vec<E> = Vec::new();
let mut passed_main = false;
compositor::with_surface_tree_downward(
main_surface,
@ -94,7 +94,13 @@ where
} else {
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
Err(err) => {
@ -103,9 +109,11 @@ where
};
}
}
if surface == main_surface {
passed_main = 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,
renderer: &mut R,
location: smithay::utils::Point<i32, smithay::utils::Physical>,
scale: smithay::utils::Scale<f64>,
alpha: f32,
scanout_node: Option<DrmNode>,
) -> Vec<C>
where
push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where
R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
C: From<CosmicMappedRenderElement<R>>,
{
match &self.element {
CosmicMappedInternal::Stack(s) => s
.popup_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
location,
scale,
alpha,
scanout_node,
),
CosmicMappedInternal::Window(w) => w
.popup_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer,
location,
scale,
alpha,
scanout_node,
),
CosmicMappedInternal::Stack(s) => s.push_popup_render_elements(
renderer,
location,
scale,
alpha,
scanout_node,
&mut |elem| push(elem.into()),
),
CosmicMappedInternal::Window(w) => w.push_popup_render_elements(
renderer,
location,
scale,
alpha,
scanout_node,
&mut |elem| push(elem.into()),
),
_ => unreachable!(),
}
.into_iter()
.map(C::from)
.collect()
}
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,
renderer: &mut R,
location: smithay::utils::Point<i32, smithay::utils::Physical>,
@ -689,15 +685,15 @@ impl CosmicMapped {
alpha: f32,
scanout_override: Option<bool>,
scanout_node: Option<DrmNode>,
) -> Vec<C>
where
push_above: &mut dyn FnMut(CosmicMappedRenderElement<R>),
push_below: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where
R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
C: From<CosmicMappedRenderElement<R>>,
{
#[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_geo = window.geometry();
let (min_size, max_size, size) = (
@ -858,21 +854,15 @@ impl CosmicMapped {
scale.x,
0.8,
) {
Ok(element) => vec![CosmicMappedRenderElement::from(element)],
Ok(element) => push_above(element.into()),
Err(err) => {
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))]
elements.extend(match &self.element {
CosmicMappedInternal::Stack(s) => s.render_elements::<R, CosmicMappedRenderElement<R>>(
match &self.element {
CosmicMappedInternal::Stack(s) => s.push_render_elements(
renderer,
location,
max_size,
@ -880,21 +870,22 @@ impl CosmicMapped {
alpha,
scanout_override,
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!(),
});
elements.into_iter().map(C::from).collect()
}
}
pub(crate) fn update_theme(&self, theme: cosmic::Theme) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,11 +9,12 @@ use std::{
use cosmic_comp_config::AppearanceConfig;
use cosmic_settings_config::shortcuts::action::ResizeDirection;
use keyframe::{ease, functions::EaseInOutCubic};
use smallvec::SmallVec;
use smithay::{
backend::{
drm::DrmNode,
renderer::element::{
AsRenderElements, RenderElement,
RenderElement,
utils::{Relocate, RelocateRenderElement, RescaleRenderElement},
},
},
@ -1443,8 +1444,8 @@ impl FloatingLayout {
renderer: &mut R,
alpha: f32,
scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>>
where
push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where
R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
@ -1454,8 +1455,6 @@ impl FloatingLayout {
let output = self.space.outputs().next().unwrap();
let output_scale = output.current_scale().fractional_scale();
let mut elements = Vec::default();
for elem in self
.animations
.iter()
@ -1470,20 +1469,17 @@ impl FloatingLayout {
.unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha));
let render_location = geometry.loc - elem.geometry().loc.as_local();
elements.extend(
elem.popup_render_elements(
renderer,
render_location
.as_logical()
.to_physical_precise_round(output_scale),
output_scale.into(),
alpha,
scanout_node,
),
elem.push_popup_render_elements(
renderer,
render_location
.as_logical()
.to_physical_precise_round(output_scale),
output_scale.into(),
alpha,
scanout_node,
push,
);
}
elements
}
#[profiling::function]
@ -1496,8 +1492,8 @@ impl FloatingLayout {
alpha: f32,
theme: &cosmic::theme::CosmicTheme,
scanout_node: Option<DrmNode>,
) -> Vec<CosmicMappedRenderElement<R>>
where
push: &mut dyn FnMut(CosmicMappedRenderElement<R>),
) where
R: AsGlowRenderer,
R::TextureId: Send + Clone + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
@ -1510,8 +1506,7 @@ impl FloatingLayout {
layers.non_exclusive_zone()
};
let output_scale = output.current_scale().fractional_scale();
let mut elements = Vec::default();
let mut lower_elements = SmallVec::<[_; 4]>::new_const();
for elem in self
.animations
@ -1525,122 +1520,9 @@ impl FloatingLayout {
.get(elem)
.map(|anim| (*anim.previous_geometry(), alpha * anim.alpha()))
.unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha));
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 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 radius = elem.corner_radius(geometry.size.as_logical(), indicator_thickness);
if indicator_thickness > 0 {
@ -1658,14 +1540,130 @@ impl FloatingLayout {
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) {

View file

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

View file

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

View file

@ -11,7 +11,7 @@ use cosmic_comp_config::ZoomMovement;
use cosmic_config::ConfigSet;
use keyframe::{ease, functions::Linear};
use smithay::{
backend::renderer::{ImportMem, Renderer, element::AsRenderElements},
backend::renderer::{ImportMem, Renderer, element::memory::MemoryRenderBufferRenderElement},
desktop::space::SpaceElement,
input::{
Seat,
@ -192,9 +192,12 @@ impl OutputZoomState {
});
}
fn render<R, C>(&mut self, renderer: &mut R, output: &Output) -> Vec<C>
where
C: From<<IcedElement<ZoomProgram> as AsRenderElements<R>>::RenderElement>,
fn render<R>(
&mut self,
renderer: &mut R,
output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
@ -208,8 +211,13 @@ impl OutputZoomState {
.to_physical(scale.fractional_scale())
.to_i32_round();
self.element
.render_elements(renderer, location, scale.fractional_scale().into(), 1.0)
self.element.push_render_elements(
renderer,
location,
scale.fractional_scale().into(),
1.0,
push,
)
}
}
@ -382,14 +390,16 @@ impl ZoomState {
None
}
pub fn render<R, C>(renderer: &mut R, output: &Output) -> Vec<C>
where
C: From<<IcedElement<ZoomProgram> as AsRenderElements<R>>::RenderElement>,
pub fn render<R>(
renderer: &mut R,
output: &Output,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
) where
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
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::{
ImportMem, Renderer,
element::{
AsRenderElements, Kind,
Kind,
memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement},
},
},
@ -910,21 +910,18 @@ impl<P: Program + Send + 'static> SpaceElement for IcedElement<P> {
}
}
impl<P, R> AsRenderElements<R> for IcedElement<P>
where
P: Program + Send + 'static,
R: Renderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
type RenderElement = MemoryRenderBufferRenderElement<R>;
fn render_elements<C: From<Self::RenderElement>>(
impl<P: Program + Send + 'static> IcedElement<P> {
pub fn push_render_elements<R>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
mut scale: Scale<f64>,
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();
// makes partial borrows easier
let internal_ref = &mut *internal;
@ -1055,11 +1052,10 @@ where
Kind::Unspecified,
) {
Ok(buffer) => {
return vec![C::from(buffer)];
push(buffer);
}
Err(err) => tracing::warn!("What? {:?}", err),
}
}
Vec::new()
}
}

View file

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

View file

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