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 core::ops::Deref;
use log::info;
@ -8,11 +9,6 @@ use slint::{
use std::cell::Cell;
use std::rc::{Rc, Weak};
pub enum RenderState {
Clean,
Dirty,
}
pub struct FemtoVGWindow {
window: Window,
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!(
self.render_state.replace(RenderState::Clean),
RenderState::Dirty
@ -50,16 +48,28 @@ impl FemtoVGWindow {
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}");
self.scale_factor.set(scale_factor);
self.window()
.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
}
pub fn scale_factor(&self) -> f32 {
fn scale_factor(&self) -> f32 {
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 {
@ -72,18 +82,15 @@ impl WindowAdapter for FemtoVGWindow {
}
fn size(&self) -> PhysicalSize {
self.size.get()
self.size_impl()
}
fn set_size(&self, size: WindowSize) {
self.size.set(size.to_physical(self.scale_factor()));
self.window.dispatch_event(WindowEvent::Resized {
size: size.to_logical(self.scale_factor()),
});
self.set_size_impl(size);
}
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 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::wayland::surfaces::popup_manager::{OnCloseCallback, PopupId};
use core::ops::Deref;
@ -10,8 +11,6 @@ use slint_interpreter::ComponentInstance;
use std::cell::{Cell, OnceCell};
use std::rc::{Rc, Weak};
use super::main_window::RenderState;
pub struct PopupWindow {
window: Window,
renderer: FemtoVGRenderer,
@ -73,7 +72,35 @@ impl PopupWindow {
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() {
info!("Popup not yet configured, skipping render");
return Ok(());
@ -98,41 +125,27 @@ impl PopupWindow {
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}");
self.scale_factor.set(scale_factor);
self.window()
.dispatch_event(WindowEvent::ScaleFactorChanged { scale_factor });
}
pub fn scale_factor(&self) -> f32 {
fn scale_factor(&self) -> f32 {
self.scale_factor.get()
}
pub fn popup_key(&self) -> Option<usize> {
self.popup_id.get().map(PopupId::key)
fn render_state(&self) -> &Cell<RenderState> {
&self.render_state
}
pub fn mark_configured(&self) {
info!("Popup window marked as configured");
self.configured.set(true);
fn size_cell(&self) -> &Cell<PhysicalSize> {
&self.size
}
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)));
self.request_redraw();
fn scale_factor_cell(&self) -> &Cell<f32> {
&self.scale_factor
}
}
@ -146,18 +159,15 @@ impl WindowAdapter for PopupWindow {
}
fn size(&self) -> PhysicalSize {
self.size.get()
self.size_impl()
}
fn set_size(&self, size: WindowSize) {
self.size.set(size.to_physical(self.scale_factor()));
self.window.dispatch_event(WindowEvent::Resized {
size: size.to_logical(self.scale_factor()),
});
self.set_size_impl(size);
}
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::{
errors::{EventLoopError, LayerShikaError, RenderingError, Result},
rendering::{
egl::context::EGLContext, femtovg::main_window::FemtoVGWindow,
egl::context::EGLContext,
femtovg::{main_window::FemtoVGWindow, renderable_window::RenderableWindow},
slint_integration::platform::CustomSlintPlatform,
},
};

View file

@ -1,6 +1,6 @@
use crate::errors::{LayerShikaError, Result};
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 layer_shika_domain::value_objects::popup_config::PopupConfig;
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;

View file

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

View file

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

View file

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