From 6621db62c85442817c7d67e325cebd27af1a0f08 Mon Sep 17 00:00:00 2001 From: drendog Date: Sat, 25 Oct 2025 23:12:56 +0200 Subject: [PATCH] refactor: wayland objects proxy --- src/windowing/mod.rs | 1 + src/windowing/proxies.rs | 194 +++++++++++++++++++++++++++++++++ src/windowing/state/builder.rs | 10 +- src/windowing/state/mod.rs | 63 +++++++---- src/windowing/system.rs | 1 + 5 files changed, 247 insertions(+), 22 deletions(-) create mode 100644 src/windowing/proxies.rs diff --git a/src/windowing/mod.rs b/src/windowing/mod.rs index 2e46a02..93c76f8 100644 --- a/src/windowing/mod.rs +++ b/src/windowing/mod.rs @@ -2,6 +2,7 @@ pub mod builder; mod config; mod globals; mod macros; +mod proxies; mod state; mod surface; mod surface_dimensions; diff --git a/src/windowing/proxies.rs b/src/windowing/proxies.rs new file mode 100644 index 0000000..7bc32b7 --- /dev/null +++ b/src/windowing/proxies.rs @@ -0,0 +1,194 @@ +use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; +use wayland_client::{protocol::{wl_pointer::WlPointer, wl_surface::WlSurface}, Connection}; +use wayland_protocols::wp::{ + fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1, + viewporter::client::wp_viewport::WpViewport, +}; +use std::{ops::Deref, rc::Rc}; +use log::{debug, error}; + +pub struct ManagedWlPointer { + pointer: Rc, + connection: Rc, +} + +impl ManagedWlPointer { + pub const fn new(pointer: Rc, connection: Rc) -> Self { + Self { + pointer, + connection, + } + } + + #[allow(dead_code)] + pub const fn inner(&self) -> &Rc { + &self.pointer + } +} + +impl Deref for ManagedWlPointer { + type Target = WlPointer; + + fn deref(&self) -> &Self::Target { + &self.pointer + } +} + +impl Drop for ManagedWlPointer { + fn drop(&mut self) { + debug!("Releasing WlPointer"); + self.pointer.release(); + if let Err(e) = self.connection.flush() { + error!("Failed to flush after releasing WlPointer: {e}"); + } + } +} + +pub struct ManagedWlSurface { + surface: Rc, + connection: Rc, +} + +impl ManagedWlSurface { + pub const fn new(surface: Rc, connection: Rc) -> Self { + Self { + surface, + connection, + } + } + + pub const fn inner(&self) -> &Rc { + &self.surface + } +} + +impl Deref for ManagedWlSurface { + type Target = WlSurface; + + fn deref(&self) -> &Self::Target { + &self.surface + } +} + +impl Drop for ManagedWlSurface { + fn drop(&mut self) { + debug!("Destroying WlSurface"); + self.surface.destroy(); + if let Err(e) = self.connection.flush() { + error!("Failed to flush after destroying WlSurface: {e}"); + } + } +} + +pub struct ManagedZwlrLayerSurfaceV1 { + layer_surface: Rc, + connection: Rc, +} + +impl ManagedZwlrLayerSurfaceV1 { + pub const fn new(layer_surface: Rc, connection: Rc) -> Self { + Self { + layer_surface, + connection, + } + } + + pub const fn inner(&self) -> &Rc { + &self.layer_surface + } +} + +impl Deref for ManagedZwlrLayerSurfaceV1 { + type Target = ZwlrLayerSurfaceV1; + + fn deref(&self) -> &Self::Target { + &self.layer_surface + } +} + +impl Drop for ManagedZwlrLayerSurfaceV1 { + fn drop(&mut self) { + debug!("Destroying ZwlrLayerSurfaceV1"); + self.layer_surface.destroy(); + if let Err(e) = self.connection.flush() { + error!("Failed to flush after destroying ZwlrLayerSurfaceV1: {e}"); + } + } +} + +pub struct ManagedWpFractionalScaleV1 { + fractional_scale: Rc, + connection: Rc, +} + +impl ManagedWpFractionalScaleV1 { + pub const fn new( + fractional_scale: Rc, + connection: Rc, + ) -> Self { + Self { + fractional_scale, + connection, + } + } + + #[allow(dead_code)] + pub const fn inner(&self) -> &Rc { + &self.fractional_scale + } +} + +impl Deref for ManagedWpFractionalScaleV1 { + type Target = WpFractionalScaleV1; + + fn deref(&self) -> &Self::Target { + &self.fractional_scale + } +} + +impl Drop for ManagedWpFractionalScaleV1 { + fn drop(&mut self) { + debug!("Destroying WpFractionalScaleV1"); + self.fractional_scale.destroy(); + if let Err(e) = self.connection.flush() { + error!("Failed to flush after destroying WpFractionalScaleV1: {e}"); + } + } +} + +pub struct ManagedWpViewport { + viewport: Rc, + connection: Rc, +} + +impl ManagedWpViewport { + pub const fn new(viewport: Rc, connection: Rc) -> Self { + Self { + viewport, + connection, + } + } + + #[allow(dead_code)] + pub const fn inner(&self) -> &Rc { + &self.viewport + } +} + +impl Deref for ManagedWpViewport { + type Target = WpViewport; + + fn deref(&self) -> &Self::Target { + &self.viewport + } +} + +impl Drop for ManagedWpViewport { + fn drop(&mut self) { + debug!("Destroying WpViewport"); + self.viewport.destroy(); + if let Err(e) = self.connection.flush() { + error!("Failed to flush after destroying WpViewport: {e}"); + } + } +} diff --git a/src/windowing/state/builder.rs b/src/windowing/state/builder.rs index a6c25a1..e8eee1c 100644 --- a/src/windowing/state/builder.rs +++ b/src/windowing/state/builder.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use slint::{platform::set_platform, PhysicalSize}; use slint_interpreter::ComponentDefinition; use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; -use wayland_client::protocol::{wl_output::WlOutput, wl_pointer::WlPointer, wl_surface::WlSurface}; +use wayland_client::{protocol::{wl_output::WlOutput, wl_pointer::WlPointer, wl_surface::WlSurface}, Connection}; use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1; use wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport; use crate::{errors::{LayerShikaError, Result}, rendering::{femtovg_window::FemtoVGWindow, slint_platform::CustomSlintPlatform}}; @@ -20,6 +20,7 @@ pub struct WindowStateBuilder { pub pointer: Option>, pub output: Option>, pub window: Option>, + pub connection: Option>, pub scale_factor: f32, pub height: u32, pub exclusive_zone: i32, @@ -109,6 +110,12 @@ impl WindowStateBuilder { self } + #[must_use] + pub fn with_connection(mut self, connection: Rc) -> Self { + self.connection = Some(connection); + self + } + pub fn build(self) -> Result { let platform = CustomSlintPlatform::new( self.window @@ -136,6 +143,7 @@ impl Default for WindowStateBuilder { pointer: None, output: None, window: None, + connection: None, scale_factor: 1.0, height: 30, exclusive_zone: -1, diff --git a/src/windowing/state/mod.rs b/src/windowing/state/mod.rs index ad6ee9b..16a9b8f 100644 --- a/src/windowing/state/mod.rs +++ b/src/windowing/state/mod.rs @@ -4,12 +4,14 @@ use log::info; use slint::{LogicalPosition, PhysicalSize, ComponentHandle}; use slint_interpreter::ComponentInstance; use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; -use wayland_client::protocol::{wl_output::WlOutput, wl_pointer::WlPointer, wl_surface::WlSurface}; -use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1; -use wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport; +use wayland_client::protocol::{wl_output::WlOutput, wl_surface::WlSurface}; use crate::rendering::femtovg_window::FemtoVGWindow; use crate::errors::{LayerShikaError, Result}; use crate::windowing::surface_dimensions::SurfaceDimensions; +use crate::windowing::proxies::{ + ManagedWlPointer, ManagedWlSurface, ManagedZwlrLayerSurfaceV1, + ManagedWpFractionalScaleV1, ManagedWpViewport, +}; pub mod builder; pub mod dispatches; @@ -23,12 +25,12 @@ enum ScalingMode { pub struct WindowState { component_instance: ComponentInstance, - surface: Rc, - layer_surface: Rc, - fractional_scale: Option>, - viewport: Option>, + viewport: Option, + fractional_scale: Option, + layer_surface: ManagedZwlrLayerSurfaceV1, + surface: ManagedWlSurface, #[allow(dead_code)] - pointer: Rc, + pointer: ManagedWlPointer, #[allow(dead_code)] output: Rc, size: PhysicalSize, @@ -58,19 +60,38 @@ impl WindowState { window.request_redraw(); + let connection = builder + .connection + .ok_or_else(|| LayerShikaError::InvalidInput("Connection is required".into()))?; + + let surface_rc = builder + .surface + .ok_or_else(|| LayerShikaError::InvalidInput("Surface is required".into()))?; + let layer_surface_rc = builder + .layer_surface + .ok_or_else(|| LayerShikaError::InvalidInput("Layer surface is required".into()))?; + let pointer_rc = builder + .pointer + .ok_or_else(|| LayerShikaError::InvalidInput("Pointer is required".into()))?; + + let viewport = builder + .viewport + .map(|vp| ManagedWpViewport::new(vp, Rc::clone(&connection))); + let fractional_scale = builder + .fractional_scale + .map(|fs| ManagedWpFractionalScaleV1::new(fs, Rc::clone(&connection))); + let layer_surface = + ManagedZwlrLayerSurfaceV1::new(layer_surface_rc, Rc::clone(&connection)); + let surface = ManagedWlSurface::new(surface_rc, Rc::clone(&connection)); + let pointer = ManagedWlPointer::new(pointer_rc, connection); + Ok(Self { component_instance, - surface: builder - .surface - .ok_or_else(|| LayerShikaError::InvalidInput("Surface is required".into()))?, - layer_surface: builder - .layer_surface - .ok_or_else(|| LayerShikaError::InvalidInput("Layer surface is required".into()))?, - fractional_scale: builder.fractional_scale, - viewport: builder.viewport, - pointer: builder - .pointer - .ok_or_else(|| LayerShikaError::InvalidInput("Pointer is required".into()))?, + viewport, + fractional_scale, + layer_surface, + surface, + pointer, output: builder .output .ok_or_else(|| LayerShikaError::InvalidInput("Output is required".into()))?, @@ -202,11 +223,11 @@ impl WindowState { } pub fn layer_surface(&self) -> Rc { - Rc::clone(&self.layer_surface) + Rc::clone(self.layer_surface.inner()) } pub fn surface(&self) -> Rc { - Rc::clone(&self.surface) + Rc::clone(self.surface.inner()) } pub const fn height(&self) -> u32 { diff --git a/src/windowing/system.rs b/src/windowing/system.rs index fdeb277..177f1c4 100644 --- a/src/windowing/system.rs +++ b/src/windowing/system.rs @@ -97,6 +97,7 @@ impl WindowingSystem { .with_scale_factor(config.scale_factor) .with_height(config.height) .with_exclusive_zone(config.exclusive_zone) + .with_connection(Rc::new(connection.clone())) .with_window(window); if let Some(fs) = &surface_ctx.fractional_scale {