milkyway/src/render.rs
2026-07-06 01:26:00 -07:00

162 lines
4.3 KiB
Rust

use smithay::{
backend::renderer::{
damage::OutputDamageTracker,
element::{
memory::MemoryRenderBufferRenderElement, solid::SolidColorRenderElement,
surface::WaylandSurfaceRenderElement, AsRenderElements, Id, Kind,
},
gles::{GlesRenderer, GlesTarget},
utils::CommitCounter,
Color32F, ImportAll, ImportDmaWl, ImportMem, ImportMemWl, Renderer, RendererSuper,
},
desktop::{space::SpaceElement, Window},
output::Output,
render_elements,
utils::{IsAlive, Physical, Point, Scale},
};
use wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode;
use crate::State;
render_elements! {
pub OutputElement<R> where R: ImportMem + ImportDmaWl + ImportMemWl;
Window=WaylandSurfaceRenderElement<R>,
Background=SolidColorRenderElement,
}
#[derive(PartialEq, Eq, Clone)]
pub struct DecoratedWindow {
pub window: Window,
}
impl DecoratedWindow {
pub fn new(window: Window) -> Self {
Self { window }
}
fn decorated(&self) -> bool {
let mut b = false;
if let Some(toplevel) = self.window.toplevel() {
toplevel.with_pending_state(|f| {
if let Some(decor) = f.decoration_mode {
b = decor == Mode::ServerSide;
}
});
}
b
}
}
impl SpaceElement for DecoratedWindow {
fn bbox(&self) -> smithay::utils::Rectangle<i32, smithay::utils::Logical> {
let mut bbox = self.window.bbox();
if self.decorated() {
bbox.loc.x -= 5;
bbox.loc.y -= 22;
}
bbox
}
fn is_in_input_region(
&self,
point: &smithay::utils::Point<f64, smithay::utils::Logical>,
) -> bool {
self.window.is_in_input_region(point)
}
fn set_activate(&self, activated: bool) {
self.window.set_activate(activated)
}
fn output_enter(
&self,
output: &Output,
overlap: smithay::utils::Rectangle<i32, smithay::utils::Logical>,
) {
self.window.output_enter(output, overlap)
}
fn output_leave(&self, output: &Output) {
self.window.output_leave(output)
}
}
impl IsAlive for DecoratedWindow {
fn alive(&self) -> bool {
self.window.alive()
}
}
impl<R> AsRenderElements<R> for DecoratedWindow
where
R: Renderer + ImportDmaWl + ImportMemWl + ImportMem + ImportAll,
<R as RendererSuper>::TextureId: Clone + Send + 'static,
{
type RenderElement = OutputElement<R>; // one enum, both variants
fn render_elements<C: From<Self::RenderElement>>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
scale: Scale<f64>,
alpha: f32,
) -> Vec<C> {
let mut elements: Vec<C> = Vec::new();
/* Start with actual window elements */
elements.extend(
self.window
.render_elements::<OutputElement<R>>(renderer, location, scale, alpha)
.into_iter()
.map(C::from),
);
/* If the window is decorated, push a solid color */
let decorated = self.decorated();
if decorated {
let mut bg_rect = self.window.geometry().to_physical_precise_round(scale);
bg_rect.size.w += 10;
bg_rect.size.h += 27;
let background = SolidColorRenderElement::new(
Id::new(),
bg_rect,
CommitCounter::default(),
Color32F::new(1.0, 0.75, 0.26, 1.0),
Kind::Unspecified,
);
elements.push(C::from(OutputElement::Background(background)));
}
elements
}
}
impl State {
pub fn render(
&self,
output: &Output,
renderer: &mut GlesRenderer,
framebuffer: &mut GlesTarget,
damage_tracker: &mut OutputDamageTracker,
) -> Result<(), Box<dyn std::error::Error>> {
// let elem = DecorationElement::
smithay::desktop::space::render_output::<_, OutputElement<GlesRenderer>, _, _>(
output,
renderer,
framebuffer,
1.0,
0,
[&self.space],
&[],
damage_tracker,
[0.07, 0.16, 0.286, 1.0],
)?;
Ok(())
}
}