refactor: extract renderable window trait

This commit is contained in:
drendog 2025-11-13 12:59:25 +01:00
parent 4d724dcd71
commit 4e38b6ff58
Signed by: dwenya
GPG key ID: 8DD77074645332D0
9 changed files with 117 additions and 63 deletions

View file

@ -1,3 +1,4 @@
use super::renderable_window::{RenderState, RenderableWindow};
use crate::errors::{RenderingError, Result}; use crate::errors::{RenderingError, Result};
use core::ops::Deref; use core::ops::Deref;
use log::info; use log::info;
@ -8,11 +9,6 @@ use slint::{
use std::cell::Cell; use std::cell::Cell;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
pub enum RenderState {
Clean,
Dirty,
}
pub struct FemtoVGWindow { pub struct FemtoVGWindow {
window: Window, window: Window,
renderer: FemtoVGRenderer, renderer: FemtoVGRenderer,
@ -35,8 +31,10 @@ impl FemtoVGWindow {
} }
}) })
} }
}
pub fn render_frame_if_dirty(&self) -> Result<()> { impl RenderableWindow for FemtoVGWindow {
fn render_frame_if_dirty(&self) -> Result<()> {
if matches!( if matches!(
self.render_state.replace(RenderState::Clean), self.render_state.replace(RenderState::Clean),
RenderState::Dirty RenderState::Dirty
@ -50,16 +48,28 @@ impl FemtoVGWindow {
Ok(()) Ok(())
} }
pub fn set_scale_factor(&self, scale_factor: f32) { fn set_scale_factor(&self, scale_factor: f32) {
info!("Setting scale factor to {scale_factor}"); info!("Setting scale factor to {scale_factor}");
self.scale_factor.set(scale_factor); self.scale_factor.set(scale_factor);
self.window() self.window()
.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor }); .dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
} }
pub fn scale_factor(&self) -> f32 { fn scale_factor(&self) -> f32 {
self.scale_factor.get() self.scale_factor.get()
} }
fn render_state(&self) -> &Cell<RenderState> {
&self.render_state
}
fn size_cell(&self) -> &Cell<PhysicalSize> {
&self.size
}
fn scale_factor_cell(&self) -> &Cell<f32> {
&self.scale_factor
}
} }
impl WindowAdapter for FemtoVGWindow { impl WindowAdapter for FemtoVGWindow {
@ -72,18 +82,15 @@ impl WindowAdapter for FemtoVGWindow {
} }
fn size(&self) -> PhysicalSize { fn size(&self) -> PhysicalSize {
self.size.get() self.size_impl()
} }
fn set_size(&self, size: WindowSize) { fn set_size(&self, size: WindowSize) {
self.size.set(size.to_physical(self.scale_factor())); self.set_size_impl(size);
self.window.dispatch_event(WindowEvent::Resized {
size: size.to_logical(self.scale_factor()),
});
} }
fn request_redraw(&self) { fn request_redraw(&self) {
self.render_state.set(RenderState::Dirty); RenderableWindow::request_redraw(self);
} }
} }

View file

@ -1,2 +1,3 @@
pub mod main_window; pub mod main_window;
pub mod popup_window; pub mod popup_window;
pub mod renderable_window;

View file

@ -1,3 +1,4 @@
use super::renderable_window::{RenderState, RenderableWindow};
use crate::errors::{RenderingError, Result}; use crate::errors::{RenderingError, Result};
use crate::wayland::surfaces::popup_manager::{OnCloseCallback, PopupId}; use crate::wayland::surfaces::popup_manager::{OnCloseCallback, PopupId};
use core::ops::Deref; use core::ops::Deref;
@ -10,8 +11,6 @@ use slint_interpreter::ComponentInstance;
use std::cell::{Cell, OnceCell}; use std::cell::{Cell, OnceCell};
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use super::main_window::RenderState;
pub struct PopupWindow { pub struct PopupWindow {
window: Window, window: Window,
renderer: FemtoVGRenderer, renderer: FemtoVGRenderer,
@ -73,7 +72,35 @@ impl PopupWindow {
info!("Popup window cleanup complete"); info!("Popup window cleanup complete");
} }
pub fn render_frame_if_dirty(&self) -> Result<()> { pub fn popup_key(&self) -> Option<usize> {
self.popup_id.get().map(PopupId::key)
}
pub fn mark_configured(&self) {
info!("Popup window marked as configured");
self.configured.set(true);
}
pub fn is_configured(&self) -> bool {
self.configured.get()
}
pub fn set_component_instance(&self, instance: ComponentInstance) {
info!("Setting component instance for popup window");
if self.component_instance.set(instance).is_err() {
info!("Component instance already set for popup window");
}
}
pub fn request_resize(&self, width: f32, height: f32) {
info!("Requesting popup resize to {}x{}", width, height);
self.set_size(WindowSize::Logical(slint::LogicalSize::new(width, height)));
RenderableWindow::request_redraw(self);
}
}
impl RenderableWindow for PopupWindow {
fn render_frame_if_dirty(&self) -> Result<()> {
if !self.configured.get() { if !self.configured.get() {
info!("Popup not yet configured, skipping render"); info!("Popup not yet configured, skipping render");
return Ok(()); return Ok(());
@ -98,41 +125,27 @@ impl PopupWindow {
Ok(()) Ok(())
} }
pub fn set_scale_factor(&self, scale_factor: f32) { fn set_scale_factor(&self, scale_factor: f32) {
info!("Setting popup scale factor to {scale_factor}"); info!("Setting popup scale factor to {scale_factor}");
self.scale_factor.set(scale_factor); self.scale_factor.set(scale_factor);
self.window() self.window()
.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor }); .dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
} }
pub fn scale_factor(&self) -> f32 { fn scale_factor(&self) -> f32 {
self.scale_factor.get() self.scale_factor.get()
} }
pub fn popup_key(&self) -> Option<usize> { fn render_state(&self) -> &Cell<RenderState> {
self.popup_id.get().map(PopupId::key) &self.render_state
} }
pub fn mark_configured(&self) { fn size_cell(&self) -> &Cell<PhysicalSize> {
info!("Popup window marked as configured"); &self.size
self.configured.set(true);
} }
pub fn is_configured(&self) -> bool { fn scale_factor_cell(&self) -> &Cell<f32> {
self.configured.get() &self.scale_factor
}
pub fn set_component_instance(&self, instance: ComponentInstance) {
info!("Setting component instance for popup window");
if self.component_instance.set(instance).is_err() {
info!("Component instance already set for popup window");
}
}
pub fn request_resize(&self, width: f32, height: f32) {
info!("Requesting popup resize to {}x{}", width, height);
self.set_size(WindowSize::Logical(slint::LogicalSize::new(width, height)));
self.request_redraw();
} }
} }
@ -146,18 +159,15 @@ impl WindowAdapter for PopupWindow {
} }
fn size(&self) -> PhysicalSize { fn size(&self) -> PhysicalSize {
self.size.get() self.size_impl()
} }
fn set_size(&self, size: WindowSize) { fn set_size(&self, size: WindowSize) {
self.size.set(size.to_physical(self.scale_factor())); self.set_size_impl(size);
self.window.dispatch_event(WindowEvent::Resized {
size: size.to_logical(self.scale_factor()),
});
} }
fn request_redraw(&self) { fn request_redraw(&self) {
self.render_state.set(RenderState::Dirty); RenderableWindow::request_redraw(self);
} }
} }

View file

@ -0,0 +1,35 @@
use crate::errors::Result;
use slint::{
PhysicalSize, WindowSize,
platform::{WindowAdapter, WindowEvent},
};
use std::cell::Cell;
pub enum RenderState {
Clean,
Dirty,
}
pub trait RenderableWindow: WindowAdapter {
fn render_frame_if_dirty(&self) -> Result<()>;
fn set_scale_factor(&self, scale_factor: f32);
fn scale_factor(&self) -> f32;
fn render_state(&self) -> &Cell<RenderState>;
fn size_cell(&self) -> &Cell<PhysicalSize>;
fn scale_factor_cell(&self) -> &Cell<f32>;
fn request_redraw(&self) {
self.render_state().set(RenderState::Dirty);
}
fn size_impl(&self) -> PhysicalSize {
self.size_cell().get()
}
fn set_size_impl(&self, size: WindowSize) {
self.size_cell().set(size.to_physical(self.scale_factor()));
self.window().dispatch_event(WindowEvent::Resized {
size: size.to_logical(self.scale_factor()),
});
}
}

View file

@ -11,7 +11,8 @@ use crate::wayland::{
use crate::{ use crate::{
errors::{EventLoopError, LayerShikaError, RenderingError, Result}, errors::{EventLoopError, LayerShikaError, RenderingError, Result},
rendering::{ rendering::{
egl::context::EGLContext, femtovg::main_window::FemtoVGWindow, egl::context::EGLContext,
femtovg::{main_window::FemtoVGWindow, renderable_window::RenderableWindow},
slint_integration::platform::CustomSlintPlatform, slint_integration::platform::CustomSlintPlatform,
}, },
}; };

View file

@ -1,6 +1,6 @@
use crate::errors::{LayerShikaError, Result}; use crate::errors::{LayerShikaError, Result};
use crate::rendering::egl::context::EGLContext; use crate::rendering::egl::context::EGLContext;
use crate::rendering::femtovg::popup_window::PopupWindow; use crate::rendering::femtovg::{popup_window::PopupWindow, renderable_window::RenderableWindow};
use crate::wayland::surfaces::display_metrics::SharedDisplayMetrics; use crate::wayland::surfaces::display_metrics::SharedDisplayMetrics;
use layer_shika_domain::value_objects::popup_config::PopupConfig; use layer_shika_domain::value_objects::popup_config::PopupConfig;
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode; use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;

View file

@ -1,18 +1,18 @@
use std::rc::Rc; use std::rc::Rc;
use crate::errors::Result; use crate::errors::Result;
use crate::rendering::femtovg::main_window::FemtoVGWindow; use crate::rendering::femtovg::renderable_window::RenderableWindow;
use crate::wayland::surfaces::window_renderer::{WindowRenderer, WindowRendererParams}; use crate::wayland::surfaces::window_renderer::{WindowRenderer, WindowRendererParams};
use slint::PhysicalSize; use slint::PhysicalSize;
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
use crate::wayland::managed_proxies::ManagedWpFractionalScaleV1; use crate::wayland::managed_proxies::ManagedWpFractionalScaleV1;
pub struct RenderingState { pub struct RenderingState<W: RenderableWindow> {
renderer: WindowRenderer, renderer: WindowRenderer<W>,
} }
impl RenderingState { impl<W: RenderableWindow> RenderingState<W> {
#[must_use] #[must_use]
pub fn new(params: WindowRendererParams) -> Self { pub fn new(params: WindowRendererParams<W>) -> Self {
Self { Self {
renderer: WindowRenderer::new(params), renderer: WindowRenderer::new(params),
} }
@ -38,7 +38,7 @@ impl RenderingState {
self.renderer.height() self.renderer.height()
} }
pub const fn window(&self) -> &Rc<FemtoVGWindow> { pub const fn window(&self) -> &Rc<W> {
self.renderer.window() self.renderer.window()
} }

View file

@ -25,7 +25,7 @@ use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1:
pub struct WindowState { pub struct WindowState {
component: ComponentState, component: ComponentState,
rendering: RenderingState, rendering: RenderingState<FemtoVGWindow>,
event_context: EventContext, event_context: EventContext,
display_metrics: SharedDisplayMetrics, display_metrics: SharedDisplayMetrics,
#[allow(dead_code)] #[allow(dead_code)]

View file

@ -1,5 +1,5 @@
use crate::errors::Result; use crate::errors::Result;
use crate::rendering::femtovg::main_window::FemtoVGWindow; use crate::rendering::femtovg::renderable_window::RenderableWindow;
use crate::wayland::managed_proxies::{ use crate::wayland::managed_proxies::{
ManagedWlSurface, ManagedZwlrLayerSurfaceV1, ManagedWpFractionalScaleV1, ManagedWpViewport, ManagedWlSurface, ManagedZwlrLayerSurfaceV1, ManagedWpFractionalScaleV1, ManagedWpViewport,
}; };
@ -17,8 +17,8 @@ enum ScalingMode {
Integer, Integer,
} }
pub struct WindowRendererParams { pub struct WindowRendererParams<W: RenderableWindow> {
pub window: Rc<FemtoVGWindow>, pub window: Rc<W>,
pub surface: ManagedWlSurface, pub surface: ManagedWlSurface,
pub layer_surface: ManagedZwlrLayerSurfaceV1, pub layer_surface: ManagedZwlrLayerSurfaceV1,
pub viewport: Option<ManagedWpViewport>, pub viewport: Option<ManagedWpViewport>,
@ -28,8 +28,8 @@ pub struct WindowRendererParams {
pub size: PhysicalSize, pub size: PhysicalSize,
} }
pub struct WindowRenderer { pub struct WindowRenderer<W: RenderableWindow> {
window: Rc<FemtoVGWindow>, window: Rc<W>,
surface: ManagedWlSurface, surface: ManagedWlSurface,
layer_surface: ManagedZwlrLayerSurfaceV1, layer_surface: ManagedZwlrLayerSurfaceV1,
viewport: Option<ManagedWpViewport>, viewport: Option<ManagedWpViewport>,
@ -40,9 +40,9 @@ pub struct WindowRenderer {
logical_size: PhysicalSize, logical_size: PhysicalSize,
} }
impl WindowRenderer { impl<W: RenderableWindow> WindowRenderer<W> {
#[must_use] #[must_use]
pub fn new(params: WindowRendererParams) -> Self { pub fn new(params: WindowRendererParams<W>) -> Self {
Self { Self {
window: params.window, window: params.window,
surface: params.surface, surface: params.surface,
@ -60,7 +60,7 @@ impl WindowRenderer {
self.window.render_frame_if_dirty() self.window.render_frame_if_dirty()
} }
pub const fn window(&self) -> &Rc<FemtoVGWindow> { pub const fn window(&self) -> &Rc<W> {
&self.window &self.window
} }
@ -176,7 +176,7 @@ impl WindowRenderer {
self.size = dimensions.to_slint_physical_size(); self.size = dimensions.to_slint_physical_size();
self.logical_size = dimensions.to_slint_logical_size(); self.logical_size = dimensions.to_slint_logical_size();
self.window.request_redraw(); RenderableWindow::request_redraw(self.window.as_ref());
} }
pub const fn logical_size(&self) -> PhysicalSize { pub const fn logical_size(&self) -> PhysicalSize {