From 070f4ecf261f723812d037b7461c909976012d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Mary=C5=84czak?= Date: Tue, 15 Aug 2023 21:51:42 +0200 Subject: [PATCH] Statically type user data of objects (#38) --- src/lib.rs | 11 ++++++++--- src/parts.rs | 22 ++++++++++++--------- src/wl_typed.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 src/wl_typed.rs diff --git a/src/lib.rs b/src/lib.rs index 2802702..1c43f36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ mod parts; mod pointer; pub mod theme; mod title; +mod wl_typed; use crate::theme::{ ColorMap, ColorTheme, BORDER_SIZE, CORNER_RADIUS, HEADER_SIZE, VISIBLE_BORDER_SIZE, @@ -36,6 +37,7 @@ use config::get_button_layout_config; use parts::DecorationParts; use pointer::{Location, MouseState}; use title::TitleText; +use wl_typed::WlTyped; /// XXX this is not result, so `must_use` when needed. type SkiaResult = Option<()>; @@ -44,7 +46,7 @@ type SkiaResult = Option<()>; #[derive(Debug)] pub struct AdwaitaFrame { /// The base surface used to create the window. - base_surface: WlSurface, + base_surface: WlTyped, /// Subcompositor to create/drop subsurfaces ondemand. subcompositor: Arc, @@ -84,7 +86,8 @@ where queue_handle: QueueHandle, frame_config: FrameConfig, ) -> Result> { - let base_surface = base_surface.wl_surface().clone(); + let base_surface = WlTyped::wrap::(base_surface.wl_surface().clone()); + let pool = SlotPool::new(1, shm)?; let decorations = Some(DecorationParts::new( @@ -402,8 +405,10 @@ where } fn click_point_moved(&mut self, surface: &WlSurface, x: f64, y: f64) -> Option<&str> { + let surface = WlTyped::wrap::(surface.clone()); + let decorations = self.decorations.as_ref()?; - let location = decorations.find_surface(surface); + let location = decorations.find_surface(&surface); if location == Location::None { return None; } diff --git a/src/parts.rs b/src/parts.rs index 6f8e385..16101e2 100644 --- a/src/parts.rs +++ b/src/parts.rs @@ -1,6 +1,6 @@ use smithay_client_toolkit::reexports::client::{ protocol::{wl_subsurface::WlSubsurface, wl_surface::WlSurface}, - Dispatch, Proxy, QueueHandle, + Dispatch, QueueHandle, }; use smithay_client_toolkit::{ @@ -8,8 +8,8 @@ use smithay_client_toolkit::{ subcompositor::{SubcompositorState, SubsurfaceData}, }; -use crate::pointer::Location; use crate::theme::{BORDER_SIZE, HEADER_SIZE}; +use crate::{pointer::Location, wl_typed::WlTyped}; /// The decoration's 'parts'. #[derive(Debug)] @@ -26,7 +26,7 @@ impl DecorationParts { pub const BOTTOM: usize = 4; pub fn new( - base_surface: &WlSurface, + base_surface: &WlTyped, subcompositor: &SubcompositorState, queue_handle: &QueueHandle, ) -> Self @@ -124,7 +124,7 @@ impl DecorationParts { &self.parts[Self::HEADER] } - pub fn find_surface(&self, surface: &WlSurface) -> Location { + pub fn find_surface(&self, surface: &WlTyped) -> Location { let pos = match self.parts.iter().position(|part| &part.surface == surface) { Some(pos) => pos, None => return Location::None, @@ -143,8 +143,8 @@ impl DecorationParts { #[derive(Debug)] pub struct Part { - pub surface: WlSurface, - pub subsurface: WlSubsurface, + pub surface: WlTyped, + pub subsurface: WlTyped, pub width: u32, pub height: u32, @@ -154,7 +154,7 @@ pub struct Part { impl Part { fn new( - parent: &WlSurface, + parent: &WlTyped, subcompositor: &SubcompositorState, queue_handle: &QueueHandle, width: u32, @@ -164,7 +164,11 @@ impl Part { where State: Dispatch + Dispatch + 'static, { - let (subsurface, surface) = subcompositor.create_subsurface(parent.clone(), queue_handle); + let (subsurface, surface) = + subcompositor.create_subsurface(parent.inner().clone(), queue_handle); + + let subsurface = WlTyped::wrap::(subsurface); + let surface = WlTyped::wrap::(surface); // Sync with the parent surface. subsurface.set_sync(); @@ -179,7 +183,7 @@ impl Part { } pub fn scale(&self) -> u32 { - self.surface.data::().unwrap().scale_factor() as u32 + self.surface.data().scale_factor() as u32 } } diff --git a/src/wl_typed.rs b/src/wl_typed.rs new file mode 100644 index 0000000..9728fb3 --- /dev/null +++ b/src/wl_typed.rs @@ -0,0 +1,51 @@ +use std::{marker::PhantomData, ops::Deref}; + +use smithay_client_toolkit::reexports::client::{Dispatch, Proxy}; + +#[derive(Debug)] +pub struct WlTyped(I, PhantomData); + +impl WlTyped +where + I: Proxy, + DATA: Send + Sync + 'static, +{ + #[allow(clippy::extra_unused_type_parameters)] + pub fn wrap(i: I) -> Self + where + STATE: Dispatch, + { + Self(i, PhantomData) + } + + pub fn inner(&self) -> &I { + &self.0 + } + + pub fn data(&self) -> &DATA { + // Generic on Self::wrap makes sure that this will never panic + #[allow(clippy::unwrap_used)] + self.0.data().unwrap() + } +} + +impl Clone for WlTyped { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Deref for WlTyped { + type Target = I; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl PartialEq for WlTyped { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl Eq for WlTyped {}