shell/elements: Handle clipping and shadows
This commit is contained in:
parent
2adebb5fe1
commit
59fd732982
7 changed files with 917 additions and 97 deletions
|
|
@ -1,7 +1,14 @@
|
|||
use crate::{
|
||||
backend::render::cursor::CursorState,
|
||||
backend::render::{
|
||||
IndicatorShader, Key, Usage,
|
||||
clipped_surface::ClippedSurfaceRenderElement,
|
||||
cursor::CursorState,
|
||||
element::{AsGlowRenderer, FromGlesError},
|
||||
shadow::ShadowShader,
|
||||
},
|
||||
hooks::{Decorations, HOOKS},
|
||||
shell::{
|
||||
element::{CosmicMappedKey, CosmicMappedKeyInner},
|
||||
focus::target::PointerFocusTarget,
|
||||
grabs::{ReleaseMode, ResizeEdge},
|
||||
},
|
||||
|
|
@ -20,9 +27,13 @@ use smithay::{
|
|||
renderer::{
|
||||
ImportAll, ImportMem, Renderer,
|
||||
element::{
|
||||
AsRenderElements, memory::MemoryRenderBufferRenderElement,
|
||||
AsRenderElements, Element, Id as RendererId, Kind, RenderElement,
|
||||
UnderlyingStorage, memory::MemoryRenderBufferRenderElement,
|
||||
surface::WaylandSurfaceRenderElement,
|
||||
},
|
||||
gles::element::PixelShaderElement,
|
||||
glow::GlowRenderer,
|
||||
utils::{CommitCounter, DamageSet, OpaqueRegions},
|
||||
},
|
||||
},
|
||||
desktop::{WindowSurfaceType, space::SpaceElement},
|
||||
|
|
@ -42,8 +53,7 @@ use smithay::{
|
|||
},
|
||||
output::Output,
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
render_elements,
|
||||
utils::{IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size},
|
||||
utils::{Buffer, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size, Transform},
|
||||
wayland::seat::WaylandFocus,
|
||||
};
|
||||
use std::{
|
||||
|
|
@ -51,7 +61,7 @@ use std::{
|
|||
fmt,
|
||||
hash::Hash,
|
||||
sync::{
|
||||
Mutex,
|
||||
Arc, Mutex,
|
||||
atomic::{AtomicBool, AtomicU8, Ordering},
|
||||
},
|
||||
};
|
||||
|
|
@ -80,6 +90,8 @@ pub struct CosmicWindowInternal {
|
|||
/// TODO: This needs to be per seat
|
||||
pointer_entered: AtomicU8,
|
||||
last_title: Mutex<String>,
|
||||
tiled: AtomicBool,
|
||||
theme: Mutex<cosmic::Theme>,
|
||||
appearance_conf: Mutex<AppearanceConfig>,
|
||||
}
|
||||
|
||||
|
|
@ -165,9 +177,9 @@ impl CosmicWindowInternal {
|
|||
!self.window.is_decorated(pending)
|
||||
}
|
||||
|
||||
/// returns if the window is currently or pending tiled
|
||||
pub fn is_tiled(&self, pending: bool) -> bool {
|
||||
self.window.is_tiled(pending).unwrap_or(false)
|
||||
/// returns if the window is currently tiled
|
||||
pub fn is_tiled(&self) -> bool {
|
||||
self.tiled.load(Ordering::Acquire)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,12 +193,19 @@ impl CosmicWindow {
|
|||
let window = window.into();
|
||||
let width = window.geometry().size.w;
|
||||
let last_title = window.title();
|
||||
|
||||
if appearance.clip_floating_windows {
|
||||
window.set_tiled(true);
|
||||
}
|
||||
|
||||
CosmicWindow(IcedElement::new(
|
||||
CosmicWindowInternal {
|
||||
window,
|
||||
activated: AtomicBool::new(false),
|
||||
pointer_entered: AtomicU8::new(0),
|
||||
last_title: Mutex::new(last_title),
|
||||
tiled: AtomicBool::new(false),
|
||||
theme: Mutex::new(theme.clone()),
|
||||
appearance_conf: Mutex::new(appearance),
|
||||
},
|
||||
(width, SSD_HEIGHT),
|
||||
|
|
@ -241,8 +260,7 @@ impl CosmicWindow {
|
|||
let mut offset = Point::from((0., 0.));
|
||||
let mut window_ui = None;
|
||||
let has_ssd = p.has_ssd(false);
|
||||
if (has_ssd || p.is_tiled(false)) && surface_type.contains(WindowSurfaceType::TOPLEVEL)
|
||||
{
|
||||
if (has_ssd || p.is_tiled()) && surface_type.contains(WindowSurfaceType::TOPLEVEL) {
|
||||
let geo = p.window.geometry();
|
||||
|
||||
let point_i32 = relative_pos.to_i32_round::<i32>();
|
||||
|
|
@ -330,6 +348,77 @@ impl CosmicWindow {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn shadow_render_element<R, C>(
|
||||
&self,
|
||||
renderer: &mut R,
|
||||
location: Point<i32, Physical>,
|
||||
scale: Scale<f64>,
|
||||
alpha: f32,
|
||||
) -> Option<C>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
R::TextureId: Send + Clone + 'static,
|
||||
C: From<CosmicWindowRenderElement<R>>,
|
||||
{
|
||||
self.0.with_program(|p| {
|
||||
let has_ssd = p.has_ssd(false);
|
||||
let is_tiled = p.is_tiled();
|
||||
let activated = p.window.is_activated(false);
|
||||
let appearance = p.appearance_conf.lock().unwrap();
|
||||
|
||||
let clip = (!is_tiled && appearance.clip_floating_windows)
|
||||
|| (is_tiled && appearance.clip_tiled_windows);
|
||||
let should_draw_shadow = if is_tiled {
|
||||
appearance.shadow_tiled_windows
|
||||
} else {
|
||||
appearance.clip_floating_windows || has_ssd
|
||||
};
|
||||
|
||||
if !should_draw_shadow {
|
||||
return None;
|
||||
}
|
||||
let mut radii = p
|
||||
.theme
|
||||
.lock()
|
||||
.unwrap()
|
||||
.cosmic()
|
||||
.radius_s()
|
||||
.map(|x| if x < 4.0 { x } else { x + 4.0 })
|
||||
.map(|x| x.round() as u8);
|
||||
if has_ssd && !clip {
|
||||
// bottom corners
|
||||
radii[1] = 0;
|
||||
radii[3] = 0;
|
||||
if is_tiled {
|
||||
// top corners
|
||||
radii[0] = 0;
|
||||
radii[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let mut geo = SpaceElement::geometry(&p.window).to_f64();
|
||||
geo.loc += location.to_f64().to_logical(scale);
|
||||
if has_ssd {
|
||||
geo.size.h += SSD_HEIGHT as f64;
|
||||
}
|
||||
|
||||
let window_key =
|
||||
CosmicMappedKey(CosmicMappedKeyInner::Window(Arc::downgrade(&self.0.0)));
|
||||
|
||||
Some(
|
||||
CosmicWindowRenderElement::Shadow(ShadowShader::element(
|
||||
renderer,
|
||||
window_key,
|
||||
geo.to_i32_round().as_local(),
|
||||
radii,
|
||||
if activated { alpha } else { alpha * 0.75 },
|
||||
scale.x,
|
||||
))
|
||||
.into(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render_elements<R, C>(
|
||||
&self,
|
||||
renderer: &mut R,
|
||||
|
|
@ -339,11 +428,36 @@ impl CosmicWindow {
|
|||
scanout_override: Option<bool>,
|
||||
) -> Vec<C>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem,
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
R::TextureId: Send + Clone + 'static,
|
||||
C: From<CosmicWindowRenderElement<R>>,
|
||||
{
|
||||
let has_ssd = self.0.with_program(|p| p.has_ssd(false));
|
||||
let (has_ssd, is_tiled, mut radii, appearance) = self.0.with_program(|p| {
|
||||
(
|
||||
p.has_ssd(false),
|
||||
p.is_tiled(),
|
||||
p.theme
|
||||
.lock()
|
||||
.unwrap()
|
||||
.cosmic()
|
||||
.radius_s()
|
||||
.map(|x| if x < 4.0 { x } else { x + 4.0 })
|
||||
.map(|x| x.round() as u8),
|
||||
*p.appearance_conf.lock().unwrap(),
|
||||
)
|
||||
});
|
||||
let clip = (!is_tiled && appearance.clip_floating_windows)
|
||||
|| (is_tiled && appearance.clip_tiled_windows);
|
||||
if has_ssd && !clip {
|
||||
// bottom corners
|
||||
radii[1] = 0;
|
||||
radii[3] = 0;
|
||||
if is_tiled {
|
||||
// top corners
|
||||
radii[0] = 0;
|
||||
radii[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let window_loc = if has_ssd {
|
||||
location + Point::from((0, (SSD_HEIGHT as f64 * scale.y) as i32))
|
||||
|
|
@ -353,14 +467,60 @@ impl CosmicWindow {
|
|||
|
||||
let mut elements = Vec::new();
|
||||
|
||||
elements.extend(self.0.with_program(|p| {
|
||||
p.window.render_elements::<R, CosmicWindowRenderElement<R>>(
|
||||
renderer,
|
||||
window_loc,
|
||||
scale,
|
||||
alpha,
|
||||
scanout_override,
|
||||
let (mut geo, bg_divider) = self.0.with_program(|p| {
|
||||
(
|
||||
SpaceElement::geometry(&p.window).to_f64(),
|
||||
p.theme.lock().unwrap().cosmic().bg_divider(),
|
||||
)
|
||||
});
|
||||
geo.loc += location.to_f64().to_logical(scale);
|
||||
if has_ssd {
|
||||
geo.size.h += SSD_HEIGHT as f64;
|
||||
}
|
||||
|
||||
if has_ssd || clip {
|
||||
let window_key =
|
||||
CosmicMappedKey(CosmicMappedKeyInner::Window(Arc::downgrade(&self.0.0)));
|
||||
|
||||
let (r, g, b, a) = bg_divider.into_components();
|
||||
let elem = CosmicWindowRenderElement::Border(IndicatorShader::element(
|
||||
renderer,
|
||||
Key::Window(Usage::Border, window_key.clone()),
|
||||
geo.to_i32_round().as_local(),
|
||||
1,
|
||||
radii,
|
||||
a * alpha,
|
||||
[r, g, b],
|
||||
));
|
||||
elements.push(elem);
|
||||
}
|
||||
|
||||
elements.extend(self.0.with_program(|p| {
|
||||
p.window
|
||||
.render_elements::<R, WaylandSurfaceRenderElement<R>>(
|
||||
renderer,
|
||||
window_loc,
|
||||
scale,
|
||||
alpha,
|
||||
scanout_override,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|elem| {
|
||||
if has_ssd {
|
||||
radii[0] = 0;
|
||||
radii[2] = 0;
|
||||
}
|
||||
if radii.iter().any(|x| *x != 0)
|
||||
&& clip
|
||||
&& ClippedSurfaceRenderElement::will_clip(&elem, scale, geo, radii)
|
||||
{
|
||||
CosmicWindowRenderElement::Clipped(ClippedSurfaceRenderElement::new(
|
||||
renderer, elem, scale, geo, radii,
|
||||
))
|
||||
} else {
|
||||
CosmicWindowRenderElement::Window(elem)
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
if has_ssd {
|
||||
|
|
@ -378,6 +538,9 @@ impl CosmicWindow {
|
|||
}
|
||||
|
||||
pub(crate) fn set_theme(&self, theme: cosmic::Theme) {
|
||||
self.0.with_program(|p| {
|
||||
*p.theme.lock().unwrap() = theme.clone();
|
||||
});
|
||||
self.0.set_theme(theme);
|
||||
}
|
||||
|
||||
|
|
@ -424,9 +587,62 @@ impl CosmicWindow {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn corner_radius(&self, geometry_size: Size<i32, Logical>) -> Option<[u8; 4]> {
|
||||
self.0
|
||||
.with_program(|p| p.window.corner_radius(geometry_size))
|
||||
pub fn set_tiled(&self, tiled: bool) {
|
||||
self.0.with_program(|p| {
|
||||
p.tiled.store(tiled, Ordering::Release);
|
||||
if !p.appearance_conf.lock().unwrap().clip_floating_windows {
|
||||
p.window.set_tiled(tiled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn corner_radius(&self, geometry_size: Size<i32, Logical>, default_radius: u8) -> [u8; 4] {
|
||||
self.0.with_program(|p| {
|
||||
let has_ssd = p.has_ssd(false);
|
||||
let is_tiled = p.is_tiled();
|
||||
let appearance = p.appearance_conf.lock().unwrap();
|
||||
|
||||
let round = (!is_tiled && appearance.clip_floating_windows)
|
||||
|| (is_tiled && appearance.clip_tiled_windows);
|
||||
let radii = p
|
||||
.theme
|
||||
.lock()
|
||||
.unwrap()
|
||||
.cosmic()
|
||||
.radius_s()
|
||||
.map(|x| if x < 4.0 { x } else { x + 4.0 })
|
||||
.map(|x| x.round() as u8);
|
||||
|
||||
match (has_ssd, round) {
|
||||
(has_ssd, true) => {
|
||||
let mut corners = p.window.corner_radius(geometry_size).unwrap_or(radii);
|
||||
|
||||
corners[0] = radii[0].max(corners[0]);
|
||||
corners[1] = if has_ssd {
|
||||
radii[1]
|
||||
} else {
|
||||
radii[1].max(corners[1])
|
||||
};
|
||||
corners[2] = radii[2].max(corners[2]);
|
||||
corners[3] = if has_ssd {
|
||||
radii[3]
|
||||
} else {
|
||||
radii[3].max(corners[3])
|
||||
};
|
||||
|
||||
corners
|
||||
}
|
||||
(true, false) => p
|
||||
.window
|
||||
.corner_radius(geometry_size)
|
||||
.map(|[a, _, c, _]| [a, radii[1], c, radii[3]])
|
||||
.unwrap_or([default_radius, radii[1], default_radius, radii[3]]),
|
||||
(false, false) => p
|
||||
.window
|
||||
.corner_radius(geometry_size)
|
||||
.unwrap_or([default_radius; 4]),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -597,7 +813,7 @@ impl SpaceElement for CosmicWindow {
|
|||
let mut bbox = SpaceElement::bbox(&p.window);
|
||||
let has_ssd = p.has_ssd(false);
|
||||
|
||||
if has_ssd || p.is_tiled(false) {
|
||||
if has_ssd || p.is_tiled() {
|
||||
bbox.loc -= Point::from((RESIZE_BORDER, RESIZE_BORDER));
|
||||
bbox.size += Size::from((RESIZE_BORDER * 2, RESIZE_BORDER * 2));
|
||||
}
|
||||
|
|
@ -716,7 +932,7 @@ impl PointerTarget<State> for CosmicWindow {
|
|||
let mut event = event.clone();
|
||||
self.0.with_program(|p| {
|
||||
let has_ssd = p.has_ssd(false);
|
||||
if has_ssd || p.is_tiled(false) {
|
||||
if has_ssd || p.is_tiled() {
|
||||
let Some(next) = Focus::under(
|
||||
&p.window,
|
||||
if has_ssd { SSD_HEIGHT } else { 0 },
|
||||
|
|
@ -742,7 +958,7 @@ impl PointerTarget<State> for CosmicWindow {
|
|||
let mut event = event.clone();
|
||||
self.0.with_program(|p| {
|
||||
let has_ssd = p.has_ssd(false);
|
||||
if has_ssd || p.is_tiled(false) {
|
||||
if has_ssd || p.is_tiled() {
|
||||
let Some(next) = Focus::under(
|
||||
&p.window,
|
||||
if has_ssd { SSD_HEIGHT } else { 0 },
|
||||
|
|
@ -955,8 +1171,193 @@ impl WaylandFocus for CosmicWindow {
|
|||
}
|
||||
}
|
||||
|
||||
render_elements! {
|
||||
pub CosmicWindowRenderElement<R> where R: ImportAll + ImportMem;
|
||||
Header = MemoryRenderBufferRenderElement<R>,
|
||||
Window = WaylandSurfaceRenderElement<R>,
|
||||
pub enum CosmicWindowRenderElement<R: Renderer + ImportAll + ImportMem> {
|
||||
Header(MemoryRenderBufferRenderElement<R>),
|
||||
Shadow(PixelShaderElement),
|
||||
Border(PixelShaderElement),
|
||||
Window(WaylandSurfaceRenderElement<R>),
|
||||
Clipped(ClippedSurfaceRenderElement<R>),
|
||||
}
|
||||
|
||||
impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R>>
|
||||
for CosmicWindowRenderElement<R>
|
||||
{
|
||||
fn from(value: MemoryRenderBufferRenderElement<R>) -> Self {
|
||||
Self::Header(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Renderer + ImportAll + ImportMem> From<WaylandSurfaceRenderElement<R>>
|
||||
for CosmicWindowRenderElement<R>
|
||||
{
|
||||
fn from(value: WaylandSurfaceRenderElement<R>) -> Self {
|
||||
Self::Window(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Renderer + ImportAll + ImportMem> From<ClippedSurfaceRenderElement<R>>
|
||||
for CosmicWindowRenderElement<R>
|
||||
{
|
||||
fn from(value: ClippedSurfaceRenderElement<R>) -> Self {
|
||||
Self::Clipped(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Element for CosmicWindowRenderElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem,
|
||||
{
|
||||
fn id(&self) -> &RendererId {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.id(),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.id(),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.id(),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.id(),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.id(),
|
||||
}
|
||||
}
|
||||
|
||||
fn current_commit(&self) -> CommitCounter {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.current_commit(),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.current_commit(),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.current_commit(),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.current_commit(),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.current_commit(),
|
||||
}
|
||||
}
|
||||
|
||||
fn src(&self) -> Rectangle<f64, Buffer> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.src(),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.src(),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.src(),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.src(),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.src(),
|
||||
}
|
||||
}
|
||||
|
||||
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.geometry(scale),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.geometry(scale),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.geometry(scale),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.geometry(scale),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.geometry(scale),
|
||||
}
|
||||
}
|
||||
|
||||
fn location(&self, scale: Scale<f64>) -> Point<i32, Physical> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.location(scale),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.location(scale),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.location(scale),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.location(scale),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.location(scale),
|
||||
}
|
||||
}
|
||||
|
||||
fn transform(&self) -> Transform {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.transform(),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.transform(),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.transform(),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.transform(),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.transform(),
|
||||
}
|
||||
}
|
||||
|
||||
fn damage_since(
|
||||
&self,
|
||||
scale: Scale<f64>,
|
||||
commit: Option<CommitCounter>,
|
||||
) -> DamageSet<i32, Physical> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.damage_since(scale, commit),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.damage_since(scale, commit),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.damage_since(scale, commit),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.damage_since(scale, commit),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.damage_since(scale, commit),
|
||||
}
|
||||
}
|
||||
|
||||
fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.opaque_regions(scale),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.opaque_regions(scale),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.opaque_regions(scale),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.opaque_regions(scale),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.opaque_regions(scale),
|
||||
}
|
||||
}
|
||||
|
||||
fn alpha(&self) -> f32 {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.alpha(),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.alpha(),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.alpha(),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.alpha(),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.alpha(),
|
||||
}
|
||||
}
|
||||
|
||||
fn kind(&self) -> Kind {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.kind(),
|
||||
CosmicWindowRenderElement::Shadow(elem) => elem.kind(),
|
||||
CosmicWindowRenderElement::Border(elem) => elem.kind(),
|
||||
CosmicWindowRenderElement::Window(elem) => elem.kind(),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.kind(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> RenderElement<R> for CosmicWindowRenderElement<R>
|
||||
where
|
||||
R: Renderer + AsGlowRenderer + ImportAll + ImportMem,
|
||||
R::TextureId: 'static,
|
||||
R::Error: FromGlesError,
|
||||
{
|
||||
fn draw(
|
||||
&self,
|
||||
frame: &mut <R>::Frame<'_, '_>,
|
||||
src: Rectangle<f64, Buffer>,
|
||||
dst: Rectangle<i32, Physical>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
opaque_regions: &[Rectangle<i32, Physical>],
|
||||
) -> Result<(), <R>::Error> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => {
|
||||
elem.draw(frame, src, dst, damage, opaque_regions)
|
||||
}
|
||||
CosmicWindowRenderElement::Shadow(elem) | CosmicWindowRenderElement::Border(elem) => {
|
||||
RenderElement::<GlowRenderer>::draw(
|
||||
elem,
|
||||
R::glow_frame_mut(frame),
|
||||
src,
|
||||
dst,
|
||||
damage,
|
||||
opaque_regions,
|
||||
)
|
||||
.map_err(FromGlesError::from_gles_error)
|
||||
}
|
||||
CosmicWindowRenderElement::Window(elem) => {
|
||||
elem.draw(frame, src, dst, damage, opaque_regions)
|
||||
}
|
||||
CosmicWindowRenderElement::Clipped(elem) => {
|
||||
elem.draw(frame, src, dst, damage, opaque_regions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn underlying_storage(&self, renderer: &mut R) -> Option<UnderlyingStorage<'_>> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(elem) => elem.underlying_storage(renderer),
|
||||
CosmicWindowRenderElement::Shadow(elem) | CosmicWindowRenderElement::Border(elem) => {
|
||||
elem.underlying_storage(renderer.glow_renderer_mut())
|
||||
}
|
||||
CosmicWindowRenderElement::Window(elem) => elem.underlying_storage(renderer),
|
||||
CosmicWindowRenderElement::Clipped(elem) => elem.underlying_storage(renderer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue