🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
#![allow(clippy::too_many_arguments)]
use smithay::{
backend::renderer::{
element::{
memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement},
surface::WaylandSurfaceRenderElement,
AsRenderElements, Kind,
},
Color32F, ImportAll, ImportMem, Renderer, Texture,
},
input::pointer::CursorImageStatus,
render_elements,
utils::{Physical, Point, Scale},
};
#[cfg(feature = "debug")]
use smithay::{
backend::renderer::{
element::{Element, Id, RenderElement},
utils::CommitCounter,
Frame,
},
utils::{Buffer, Logical, Rectangle, Size, Transform},
};
pub static CLEAR_COLOR: Color32F = Color32F::new(0.8, 0.8, 0.9, 1.0);
pub static CLEAR_COLOR_FULLSCREEN: Color32F = Color32F::new(0.0, 0.0, 0.0, 0.0);
pub struct PointerElement {
buffer: Option<MemoryRenderBuffer>,
status: CursorImageStatus,
}
impl Default for PointerElement {
fn default() -> Self {
Self {
buffer: Default::default(),
status: CursorImageStatus::default_named(),
}
}
}
impl PointerElement {
pub fn set_status(&mut self, status: CursorImageStatus) {
self.status = status;
}
pub fn set_buffer(&mut self, buffer: MemoryRenderBuffer) {
self.buffer = Some(buffer);
}
}
render_elements! {
pub PointerRenderElement<R> where R: ImportAll + ImportMem;
Surface=WaylandSurfaceRenderElement<R>,
Memory=MemoryRenderBufferRenderElement<R>,
}
impl<R: Renderer> std::fmt::Debug for PointerRenderElement<R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Surface(arg0) => f.debug_tuple("Surface").field(arg0).finish(),
Self::Memory(arg0) => f.debug_tuple("Memory").field(arg0).finish(),
Self::_GenericCatcher(arg0) => f.debug_tuple("_GenericCatcher").field(arg0).finish(),
}
}
}
impl<T: Texture + Clone + Send + 'static, R> AsRenderElements<R> for PointerElement
where
R: Renderer<TextureId = T> + ImportAll + ImportMem,
{
type RenderElement = PointerRenderElement<R>;
fn render_elements<E>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
scale: Scale<f64>,
alpha: f32,
) -> Vec<E>
where
E: From<PointerRenderElement<R>>,
{
match &self.status {
CursorImageStatus::Hidden => vec![],
// Always render `Default` for a named shape.
CursorImageStatus::Named(_) => {
if let Some(buffer) = self.buffer.as_ref() {
vec![PointerRenderElement::<R>::from(
MemoryRenderBufferRenderElement::from_buffer(
renderer,
location.to_f64(),
buffer,
None,
None,
None,
Kind::Cursor,
)
.expect("Lost system pointer buffer"),
)
.into()]
} else {
vec![]
}
}
CursorImageStatus::Surface(surface) => {
let elements: Vec<PointerRenderElement<R>> =
smithay::backend::renderer::element::surface::render_elements_from_surface_tree(
renderer,
surface,
location,
scale,
alpha,
Kind::Cursor,
);
elements.into_iter().map(E::from).collect()
}
}
}
}
#[cfg(feature = "debug")]
pub static FPS_NUMBERS_PNG: &[u8] = include_bytes!("../resources/numbers.png");
#[cfg(feature = "debug")]
#[derive(Debug, Clone)]
pub struct FpsElement<T: Texture> {
id: Id,
value: u32,
texture: T,
commit_counter: CommitCounter,
}
#[cfg(feature = "debug")]
impl<T: Texture> FpsElement<T> {
pub fn new(texture: T) -> Self {
FpsElement {
id: Id::new(),
texture,
value: 0,
commit_counter: CommitCounter::default(),
}
}
pub fn update_fps(&mut self, fps: u32) {
if self.value != fps {
self.value = fps;
self.commit_counter.increment();
}
}
}
#[cfg(feature = "debug")]
impl<T> Element for FpsElement<T>
where
T: Texture + 'static,
{
fn id(&self) -> &Id {
&self.id
}
fn location(&self, _scale: Scale<f64>) -> Point<i32, Physical> {
(0, 0).into()
}
fn src(&self) -> Rectangle<f64, Buffer> {
let digits = if self.value < 10 {
1
} else if self.value < 100 {
2
} else {
3
};
Rectangle::from_size((24 * digits, 35).into()).to_f64()
}
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
let digits = if self.value < 10 {
1
} else if self.value < 100 {
2
} else {
3
};
Rectangle::from_size((24 * digits, 35).into()).to_physical_precise_round(scale)
}
fn current_commit(&self) -> CommitCounter {
self.commit_counter
}
}
#[cfg(feature = "debug")]
impl<R> RenderElement<R> for FpsElement<R::TextureId>
where
R: Renderer + ImportAll,
R::TextureId: 'static,
{
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> {
// FIXME: respect the src for cropping
let scale = dst.size.to_f64() / self.src().size;
let value_str = std::cmp::min(self.value, 999).to_string();
let mut offset: Point<f64, Physical> = Point::from((0.0, 0.0));
for digit in value_str.chars().map(|d| d.to_digit(10).unwrap()) {
let digit_location = dst.loc.to_f64() + offset;
let digit_size = Size::<i32, Logical>::from((22, 35)).to_f64().to_physical(scale);
let dst = Rectangle::new(
digit_location.to_i32_round(),
((digit_size.to_point() + digit_location).to_i32_round() - digit_location.to_i32_round())
.to_size(),
);
let damage = damage
.iter()
.cloned()
.flat_map(|x| x.intersection(dst))
.map(|mut x| {
x.loc -= dst.loc;
x
})
.collect::<Vec<_>>();
let texture_src: Rectangle<i32, Buffer> = match digit {
9 => Rectangle::from_size((22, 35).into()),
6 => Rectangle::new((22, 0).into(), (22, 35).into()),
3 => Rectangle::new((44, 0).into(), (22, 35).into()),
1 => Rectangle::new((66, 0).into(), (22, 35).into()),
8 => Rectangle::new((0, 35).into(), (22, 35).into()),
0 => Rectangle::new((22, 35).into(), (22, 35).into()),
2 => Rectangle::new((44, 35).into(), (22, 35).into()),
7 => Rectangle::new((0, 70).into(), (22, 35).into()),
4 => Rectangle::new((22, 70).into(), (22, 35).into()),
5 => Rectangle::new((44, 70).into(), (22, 35).into()),
_ => unreachable!(),
};
frame.render_texture_from_to(
&self.texture,
texture_src.to_f64(),
dst,
&damage,
&[],
Transform::Normal,
1.0,
)?;
offset += Point::from((24.0, 0.0)).to_physical(scale);
}
Ok(())
}
}