element: Refactor element acquisition to be push based
This commit is contained in:
parent
178c6593dc
commit
e4c0716951
18 changed files with 1096 additions and 1137 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue