refactor: state builder to get rid of option fields
parent
9b7818e280
commit
0759b688cf
|
@ -4,9 +4,8 @@ use crate::{
|
||||||
rendering::{egl_context::EGLContext, femtovg_window::FemtoVGWindow},
|
rendering::{egl_context::EGLContext, femtovg_window::FemtoVGWindow},
|
||||||
};
|
};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use config::WindowConfig;
|
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
use slint::{platform::femtovg_renderer::FemtoVGRenderer, LogicalPosition};
|
use slint::{platform::femtovg_renderer::FemtoVGRenderer, LogicalPosition, PhysicalSize};
|
||||||
use slint_interpreter::ComponentInstance;
|
use slint_interpreter::ComponentInstance;
|
||||||
use smithay_client_toolkit::reexports::{
|
use smithay_client_toolkit::reexports::{
|
||||||
calloop::{self, EventLoop, Interest, LoopHandle, Mode, PostAction},
|
calloop::{self, EventLoop, Interest, LoopHandle, Mode, PostAction},
|
||||||
|
@ -14,6 +13,7 @@ use smithay_client_toolkit::reexports::{
|
||||||
zwlr_layer_shell_v1::ZwlrLayerShellV1, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
zwlr_layer_shell_v1::ZwlrLayerShellV1, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use state::builder::WindowStateBuilder;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
globals::{registry_queue_init, GlobalList},
|
globals::{registry_queue_init, GlobalList},
|
||||||
|
@ -37,32 +37,46 @@ pub struct WindowingSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowingSystem {
|
impl WindowingSystem {
|
||||||
fn new(config: &mut WindowConfig) -> Result<Self> {
|
fn new(config: &mut config::WindowConfig) -> Result<Self> {
|
||||||
info!("Initializing WindowingSystem");
|
info!("Initializing WindowingSystem");
|
||||||
let connection = Rc::new(Connection::connect_to_env()?);
|
let connection = Rc::new(Connection::connect_to_env()?);
|
||||||
|
|
||||||
let global_list = Self::initialize_registry(&connection)?;
|
let global_list = Self::initialize_registry(&connection)?;
|
||||||
let mut event_queue = connection.new_event_queue();
|
let event_queue = connection.new_event_queue();
|
||||||
|
|
||||||
let (compositor, output, layer_shell, seat) =
|
let (compositor, output, layer_shell, seat) =
|
||||||
Self::bind_globals(&global_list, &event_queue.handle())?;
|
Self::bind_globals(&global_list, &event_queue.handle())?;
|
||||||
|
|
||||||
let mut state = WindowState::new(config)?;
|
let surface = Rc::new(compositor.create_surface(&event_queue.handle(), ()));
|
||||||
|
let layer_surface = Rc::new(layer_shell.get_layer_surface(
|
||||||
Self::setup_surface(
|
&surface,
|
||||||
&compositor,
|
Some(&output),
|
||||||
&output,
|
config.layer,
|
||||||
&layer_shell,
|
config.namespace.clone(),
|
||||||
&seat,
|
|
||||||
&event_queue.handle(),
|
&event_queue.handle(),
|
||||||
&mut state,
|
(),
|
||||||
config,
|
));
|
||||||
);
|
|
||||||
|
|
||||||
Self::wait_for_configure(&mut event_queue, &mut state)?;
|
let pointer = Rc::new(seat.get_pointer(&event_queue.handle(), ()));
|
||||||
|
|
||||||
|
Self::configure_layer_surface(&layer_surface, &surface, config);
|
||||||
|
|
||||||
|
let mut state_builder = WindowStateBuilder::new()
|
||||||
|
.component_definition(config.component_definition.take().unwrap())
|
||||||
|
.surface(Rc::clone(&surface))
|
||||||
|
.layer_surface(Rc::clone(&layer_surface))
|
||||||
|
.pointer(Rc::clone(&pointer))
|
||||||
|
.scale_factor(config.scale_factor)
|
||||||
|
.height(config.height)
|
||||||
|
.exclusive_zone(config.exclusive_zone);
|
||||||
|
|
||||||
|
//Self::wait_for_configure(&mut event_queue, &mut state_builder)?;
|
||||||
let display = connection.display();
|
let display = connection.display();
|
||||||
|
|
||||||
Self::initialize_renderer(&mut state, &display, config)?;
|
let window = Self::initialize_renderer(&state_builder, &display, config)?;
|
||||||
|
state_builder = state_builder.window(window);
|
||||||
|
|
||||||
|
let state = state_builder.build()?;
|
||||||
|
|
||||||
let event_loop = EventLoop::try_new().context("Failed to create event loop")?;
|
let event_loop = EventLoop::try_new().context("Failed to create event loop")?;
|
||||||
|
|
||||||
|
@ -94,38 +108,10 @@ impl WindowingSystem {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_surface(
|
|
||||||
compositor: &WlCompositor,
|
|
||||||
output: &WlOutput,
|
|
||||||
layer_shell: &ZwlrLayerShellV1,
|
|
||||||
seat: &WlSeat,
|
|
||||||
queue_handle: &QueueHandle<WindowState>,
|
|
||||||
state: &mut WindowState,
|
|
||||||
config: &WindowConfig,
|
|
||||||
) {
|
|
||||||
let surface = Rc::new(compositor.create_surface(queue_handle, ()));
|
|
||||||
let layer_surface = Rc::new(layer_shell.get_layer_surface(
|
|
||||||
&surface,
|
|
||||||
Some(output),
|
|
||||||
config.layer,
|
|
||||||
config.namespace.clone(),
|
|
||||||
queue_handle,
|
|
||||||
(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let pointer = Rc::new(seat.get_pointer(queue_handle, ()));
|
|
||||||
|
|
||||||
state.set_surface(Rc::clone(&surface));
|
|
||||||
state.set_layer_surface(Rc::clone(&layer_surface));
|
|
||||||
state.set_pointer(pointer);
|
|
||||||
|
|
||||||
Self::configure_layer_surface(&layer_surface, &surface, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn configure_layer_surface(
|
fn configure_layer_surface(
|
||||||
layer_surface: &Rc<ZwlrLayerSurfaceV1>,
|
layer_surface: &Rc<ZwlrLayerSurfaceV1>,
|
||||||
surface: &WlSurface,
|
surface: &WlSurface,
|
||||||
config: &WindowConfig,
|
config: &config::WindowConfig,
|
||||||
) {
|
) {
|
||||||
layer_surface.set_anchor(config.anchor);
|
layer_surface.set_anchor(config.anchor);
|
||||||
layer_surface.set_margin(
|
layer_surface.set_margin(
|
||||||
|
@ -141,29 +127,14 @@ impl WindowingSystem {
|
||||||
surface.commit();
|
surface.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_configure(
|
fn create_renderer(
|
||||||
event_queue: &mut EventQueue<WindowState>,
|
state_builder: &WindowStateBuilder,
|
||||||
state: &mut WindowState,
|
display: &WlDisplay,
|
||||||
) -> Result<()> {
|
) -> Result<FemtoVGRenderer> {
|
||||||
info!("Waiting for surface to be configured...");
|
let size = state_builder.size.unwrap_or(PhysicalSize::new(1, 1));
|
||||||
event_queue
|
let surface = state_builder
|
||||||
.blocking_dispatch(state)
|
.surface
|
||||||
.context("Failed to dispatch events")?;
|
.as_ref()
|
||||||
info!("Blocking dispatch completed");
|
|
||||||
let size = state.output_size();
|
|
||||||
if size.width > 1 && size.height > 1 {
|
|
||||||
info!("Configured output size: {:?}", size);
|
|
||||||
} else {
|
|
||||||
return Err(anyhow::anyhow!("Invalid output size: {:?}", size));
|
|
||||||
}
|
|
||||||
debug!("Surface configuration complete");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_renderer(state: &WindowState, display: &WlDisplay) -> Result<FemtoVGRenderer> {
|
|
||||||
let size = state.size();
|
|
||||||
let surface = state
|
|
||||||
.surface()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("Failed to get surface"))?;
|
.ok_or_else(|| anyhow::anyhow!("Failed to get surface"))?;
|
||||||
|
|
||||||
debug!("Creating EGL context with size: {:?}", size);
|
debug!("Creating EGL context with size: {:?}", size);
|
||||||
|
@ -179,14 +150,14 @@ impl WindowingSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_renderer(
|
fn initialize_renderer(
|
||||||
state: &mut WindowState,
|
state_builder: &WindowStateBuilder,
|
||||||
display: &WlDisplay,
|
display: &WlDisplay,
|
||||||
config: &WindowConfig,
|
config: &config::WindowConfig,
|
||||||
) -> Result<()> {
|
) -> Result<Rc<FemtoVGWindow>> {
|
||||||
let renderer = Self::create_renderer(state, display)?;
|
let renderer = Self::create_renderer(state_builder, display)?;
|
||||||
|
|
||||||
let femtovg_window = FemtoVGWindow::new(renderer);
|
let femtovg_window = FemtoVGWindow::new(renderer);
|
||||||
let size = state.size();
|
let size = state_builder.size.unwrap_or_default();
|
||||||
info!("Initializing UI with size: {:?}", size);
|
info!("Initializing UI with size: {:?}", size);
|
||||||
femtovg_window.set_size(slint::WindowSize::Physical(size));
|
femtovg_window.set_size(slint::WindowSize::Physical(size));
|
||||||
femtovg_window.set_scale_factor(config.scale_factor);
|
femtovg_window.set_scale_factor(config.scale_factor);
|
||||||
|
@ -194,9 +165,7 @@ impl WindowingSystem {
|
||||||
|
|
||||||
debug!("Creating Slint component instance");
|
debug!("Creating Slint component instance");
|
||||||
|
|
||||||
state.set_window(Rc::clone(&femtovg_window));
|
Ok(femtovg_window)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_loop_handle(&self) -> LoopHandle<'static, WindowState> {
|
pub fn event_loop_handle(&self) -> LoopHandle<'static, WindowState> {
|
||||||
|
@ -206,7 +175,7 @@ impl WindowingSystem {
|
||||||
pub fn run(&mut self) -> Result<()> {
|
pub fn run(&mut self) -> Result<()> {
|
||||||
info!("Starting WindowingSystem main loop");
|
info!("Starting WindowingSystem main loop");
|
||||||
|
|
||||||
self.initialize_component()?;
|
self.state.window().render_frame_if_dirty()?;
|
||||||
self.setup_wayland_event_source()?;
|
self.setup_wayland_event_source()?;
|
||||||
|
|
||||||
let connection = Rc::clone(&self.connection);
|
let connection = Rc::clone(&self.connection);
|
||||||
|
@ -223,17 +192,6 @@ impl WindowingSystem {
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to run event loop: {}", e))
|
.map_err(|e| anyhow::anyhow!("Failed to run event loop: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_component(&mut self) -> Result<()> {
|
|
||||||
if let Some(window) = &self.state.window() {
|
|
||||||
window.render_frame_if_dirty()?;
|
|
||||||
} else {
|
|
||||||
return Err(anyhow::anyhow!("Window not initialized"));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state.show_component()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_wayland_event_source(&self) -> Result<()> {
|
fn setup_wayland_event_source(&self) -> Result<()> {
|
||||||
debug!("Setting up Wayland event source");
|
debug!("Setting up Wayland event source");
|
||||||
|
|
||||||
|
@ -267,21 +225,17 @@ impl WindowingSystem {
|
||||||
|
|
||||||
slint::platform::update_timers_and_animations();
|
slint::platform::update_timers_and_animations();
|
||||||
|
|
||||||
if let Some(window) = shared_data.window() {
|
shared_data.window().render_frame_if_dirty()?;
|
||||||
window.render_frame_if_dirty()?;
|
|
||||||
} else {
|
|
||||||
return Err(anyhow::anyhow!("Window not initialized"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn component_instance(&self) -> Option<&ComponentInstance> {
|
pub const fn component_instance(&self) -> &ComponentInstance {
|
||||||
self.state.component_instance()
|
self.state.component_instance()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window(&self) -> Option<Rc<FemtoVGWindow>> {
|
pub fn window(&self) -> Rc<FemtoVGWindow> {
|
||||||
self.state().window().as_ref().map(Rc::clone)
|
self.state.window()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn state(&self) -> &WindowState {
|
pub const fn state(&self) -> &WindowState {
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
use std::rc::Rc;
|
||||||
|
use slint::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_pointer::WlPointer, wl_surface::WlSurface};
|
||||||
|
use crate::rendering::{femtovg_window::FemtoVGWindow, slint_platform::CustomSlintPlatform};
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use super::WindowState;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct WindowStateBuilder {
|
||||||
|
pub component_definition: Option<ComponentDefinition>,
|
||||||
|
pub surface: Option<Rc<WlSurface>>,
|
||||||
|
pub layer_surface: Option<Rc<ZwlrLayerSurfaceV1>>,
|
||||||
|
pub size: Option<PhysicalSize>,
|
||||||
|
pub output_size: Option<PhysicalSize>,
|
||||||
|
pub pointer: Option<Rc<WlPointer>>,
|
||||||
|
pub window: Option<Rc<FemtoVGWindow>>,
|
||||||
|
pub scale_factor: f32,
|
||||||
|
pub height: u32,
|
||||||
|
pub exclusive_zone: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowStateBuilder {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
component_definition: None,
|
||||||
|
surface: None,
|
||||||
|
layer_surface: None,
|
||||||
|
size: None,
|
||||||
|
output_size: None,
|
||||||
|
pointer: None,
|
||||||
|
window: None,
|
||||||
|
scale_factor: 1.0,
|
||||||
|
height: 30,
|
||||||
|
exclusive_zone: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface(mut self, surface: Rc<WlSurface>) -> Self {
|
||||||
|
self.surface = Some(surface);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layer_surface(mut self, layer_surface: Rc<ZwlrLayerSurfaceV1>) -> Self {
|
||||||
|
self.layer_surface = Some(layer_surface);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn size(mut self, size: PhysicalSize) -> Self {
|
||||||
|
self.size = Some(size);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn output_size(mut self, output_size: PhysicalSize) -> Self {
|
||||||
|
self.output_size = Some(output_size);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pointer(mut self, pointer: Rc<WlPointer>) -> Self {
|
||||||
|
self.pointer = Some(pointer);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window(mut self, window: Rc<FemtoVGWindow>) -> Self {
|
||||||
|
self.window = Some(window);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn scale_factor(mut self, scale_factor: f32) -> Self {
|
||||||
|
self.scale_factor = scale_factor;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn height(mut self, height: u32) -> Self {
|
||||||
|
self.height = height;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn exclusive_zone(mut self, exclusive_zone: i32) -> Self {
|
||||||
|
self.exclusive_zone = exclusive_zone;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn component_definition(mut self, component_definition: ComponentDefinition) -> Self {
|
||||||
|
self.component_definition = Some(component_definition);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<WindowState> {
|
||||||
|
let platform = CustomSlintPlatform::new(Rc::clone(self.window.as_ref().unwrap()));
|
||||||
|
slint::platform::set_platform(Box::new(platform))
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to set platform: {:?}", e))?;
|
||||||
|
|
||||||
|
WindowState::new(self)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::impl_empty_dispatch;
|
use crate::impl_empty_dispatch;
|
||||||
use log::{info, warn};
|
use log::info;
|
||||||
use slint::{
|
use slint::{
|
||||||
platform::{PointerEventButton, WindowEvent},
|
platform::{PointerEventButton, WindowEvent},
|
||||||
PhysicalSize,
|
PhysicalSize,
|
||||||
|
@ -42,20 +42,10 @@ impl Dispatch<ZwlrLayerSurfaceV1, ()> for WindowState {
|
||||||
info!("Layer surface configured with size: {}x{}", width, height);
|
info!("Layer surface configured with size: {}x{}", width, height);
|
||||||
layer_surface.ack_configure(serial);
|
layer_surface.ack_configure(serial);
|
||||||
if width > 0 && height > 0 {
|
if width > 0 && height > 0 {
|
||||||
state
|
state.update_size(state.output_size().width, state.height());
|
||||||
.update_size(state.output_size().width, state.height())
|
|
||||||
.unwrap_or(warn!(
|
|
||||||
"Failed to update window size with width: {} and height: {}",
|
|
||||||
width, height
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
let current_size = state.output_size();
|
let current_size = state.output_size();
|
||||||
state
|
state.update_size(current_size.width, current_size.height);
|
||||||
.update_size(current_size.width, current_size.height)
|
|
||||||
.unwrap_or(warn!(
|
|
||||||
"Failed to update window size with width: {} and height: {}",
|
|
||||||
width, height
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zwlr_layer_surface_v1::Event::Closed => {
|
zwlr_layer_surface_v1::Event::Closed => {
|
||||||
|
@ -125,33 +115,23 @@ impl Dispatch<WlPointer, ()> for WindowState {
|
||||||
surface_x,
|
surface_x,
|
||||||
surface_y,
|
surface_y,
|
||||||
..
|
..
|
||||||
} => {
|
|
||||||
state.set_current_pointer_position(surface_x, surface_y);
|
|
||||||
let logical_position = state.current_pointer_position();
|
|
||||||
if let Some(window) = state.window() {
|
|
||||||
window.dispatch_event(WindowEvent::PointerMoved {
|
|
||||||
position: logical_position,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
| wl_pointer::Event::Motion {
|
||||||
wl_pointer::Event::Leave { .. } => {
|
|
||||||
if let Some(window) = state.window() {
|
|
||||||
window.dispatch_event(WindowEvent::PointerExited);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_pointer::Event::Motion {
|
|
||||||
surface_x,
|
surface_x,
|
||||||
surface_y,
|
surface_y,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
state.set_current_pointer_position(surface_x, surface_y);
|
state.set_current_pointer_position(surface_x, surface_y);
|
||||||
if let Some(window) = state.window() {
|
|
||||||
let logical_position = state.current_pointer_position();
|
let logical_position = state.current_pointer_position();
|
||||||
window.dispatch_event(WindowEvent::PointerMoved {
|
state.window().dispatch_event(WindowEvent::PointerMoved {
|
||||||
position: logical_position,
|
position: *logical_position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_pointer::Event::Leave { .. } => {
|
||||||
|
state.window().dispatch_event(WindowEvent::PointerExited);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_pointer::Event::Button {
|
wl_pointer::Event::Button {
|
||||||
state: button_state,
|
state: button_state,
|
||||||
..
|
..
|
||||||
|
@ -159,16 +139,14 @@ impl Dispatch<WlPointer, ()> for WindowState {
|
||||||
let event = match button_state {
|
let event = match button_state {
|
||||||
WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed {
|
WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed {
|
||||||
button: PointerEventButton::Left,
|
button: PointerEventButton::Left,
|
||||||
position: state.current_pointer_position(),
|
position: *state.current_pointer_position(),
|
||||||
},
|
},
|
||||||
_ => WindowEvent::PointerReleased {
|
_ => WindowEvent::PointerReleased {
|
||||||
button: PointerEventButton::Left,
|
button: PointerEventButton::Left,
|
||||||
position: state.current_pointer_position(),
|
position: *state.current_pointer_position(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let Some(window) = state.window() {
|
state.window().dispatch_event(event);
|
||||||
window.dispatch_event(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use builder::WindowStateBuilder;
|
||||||
use log::info;
|
use log::info;
|
||||||
use slint::{LogicalPosition, PhysicalSize, ComponentHandle};
|
use slint::{LogicalPosition, PhysicalSize, ComponentHandle};
|
||||||
use slint_interpreter::{ComponentDefinition, ComponentInstance};
|
use slint_interpreter::ComponentInstance;
|
||||||
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 wayland_client::protocol::{wl_pointer::WlPointer, wl_surface::WlSurface};
|
use wayland_client::protocol::wl_surface::WlSurface;
|
||||||
use crate::rendering::{femtovg_window::FemtoVGWindow, slint_platform::CustomSlintPlatform};
|
use crate::rendering::femtovg_window::FemtoVGWindow;
|
||||||
use super::WindowConfig;
|
use anyhow::{Context, Result};
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
|
pub mod builder;
|
||||||
pub mod dispatches;
|
pub mod dispatches;
|
||||||
|
|
||||||
pub struct WindowState {
|
pub struct WindowState {
|
||||||
component_definition: ComponentDefinition,
|
component_instance: ComponentInstance,
|
||||||
component_instance: Option<ComponentInstance>,
|
surface: Rc<WlSurface>,
|
||||||
surface: Option<Rc<WlSurface>>,
|
layer_surface: Rc<ZwlrLayerSurfaceV1>,
|
||||||
layer_surface: Option<Rc<ZwlrLayerSurfaceV1>>,
|
|
||||||
size: PhysicalSize,
|
size: PhysicalSize,
|
||||||
output_size: PhysicalSize,
|
output_size: PhysicalSize,
|
||||||
pointer: Option<Rc<WlPointer>>,
|
window: Rc<FemtoVGWindow>,
|
||||||
window: Option<Rc<FemtoVGWindow>>,
|
|
||||||
current_pointer_position: LogicalPosition,
|
current_pointer_position: LogicalPosition,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
@ -26,68 +25,42 @@ pub struct WindowState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowState {
|
impl WindowState {
|
||||||
pub fn new(config: &mut WindowConfig) -> Result<Self> {
|
pub fn new(builder: WindowStateBuilder) -> Result<Self> {
|
||||||
let component_definition = config
|
let component_definition = builder
|
||||||
.component_definition
|
.component_definition
|
||||||
.take()
|
.context("Component definition is required")?;
|
||||||
.ok_or_else(|| anyhow::anyhow!("Component definition is required"))?;
|
let component_instance = component_definition
|
||||||
|
.create()
|
||||||
|
.context("Failed to create component instance")?;
|
||||||
|
component_instance
|
||||||
|
.show()
|
||||||
|
.context("Failed to show component")?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
surface: None,
|
component_instance,
|
||||||
layer_surface: None,
|
surface: builder.surface.context("Surface is required")?,
|
||||||
size: PhysicalSize::default(),
|
layer_surface: builder.layer_surface.context("Layer surface is required")?,
|
||||||
output_size: PhysicalSize::default(),
|
size: builder.size.unwrap_or_default(),
|
||||||
pointer: None,
|
output_size: builder.output_size.unwrap_or_default(),
|
||||||
window: None,
|
window: builder.window.context("Window is required")?,
|
||||||
current_pointer_position: LogicalPosition::default(),
|
current_pointer_position: LogicalPosition::default(),
|
||||||
scale_factor: config.scale_factor,
|
scale_factor: builder.scale_factor,
|
||||||
height: config.height,
|
height: builder.height,
|
||||||
exclusive_zone: config.exclusive_zone,
|
exclusive_zone: builder.exclusive_zone,
|
||||||
component_definition,
|
|
||||||
component_instance: None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_component(&mut self) -> Result<()> {
|
pub fn update_size(&mut self, width: u32, height: u32) {
|
||||||
if let Some(window) = &self.window {
|
|
||||||
let platform = CustomSlintPlatform::new(Rc::clone(window));
|
|
||||||
slint::platform::set_platform(Box::new(platform))
|
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to set platform: {:?}", e))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.component_instance = Some(self.component_definition.create()?);
|
|
||||||
|
|
||||||
if let Some(component_instance) = &self.component_instance {
|
|
||||||
component_instance.show()?;
|
|
||||||
} else {
|
|
||||||
return Err(anyhow::anyhow!("Component instance not initialized"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_size(&mut self, width: u32, height: u32) -> Result<()> {
|
|
||||||
let new_size = PhysicalSize::new(width, height);
|
let new_size = PhysicalSize::new(width, height);
|
||||||
if let Some(window) = &self.window() {
|
|
||||||
info!("Updating window size to {}x{}", width, height);
|
info!("Updating window size to {}x{}", width, height);
|
||||||
window.set_size(slint::WindowSize::Physical(new_size));
|
self.window.set_size(slint::WindowSize::Physical(new_size));
|
||||||
window.set_scale_factor(self.scale_factor);
|
self.window.set_scale_factor(self.scale_factor);
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(layer_surface) = &self.layer_surface() {
|
|
||||||
info!("Updating layer surface size to {}x{}", width, height);
|
info!("Updating layer surface size to {}x{}", width, height);
|
||||||
layer_surface.set_size(width, height);
|
self.layer_surface.set_size(width, height);
|
||||||
layer_surface.set_exclusive_zone(self.exclusive_zone);
|
self.layer_surface.set_exclusive_zone(self.exclusive_zone);
|
||||||
}
|
|
||||||
|
|
||||||
match self.surface.as_ref() {
|
self.surface.commit();
|
||||||
Some(surface) => surface.commit(),
|
|
||||||
None => {
|
|
||||||
return Err(anyhow::anyhow!("Surface not initialized"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.size = new_size;
|
self.size = new_size;
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
|
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
|
||||||
|
@ -99,22 +72,24 @@ impl WindowState {
|
||||||
self.current_pointer_position = logical_position;
|
self.current_pointer_position = logical_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn size(&self) -> PhysicalSize {
|
pub const fn size(&self) -> &PhysicalSize {
|
||||||
self.size
|
&self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn current_pointer_position(&self) -> LogicalPosition {
|
pub const fn current_pointer_position(&self) -> &LogicalPosition {
|
||||||
self.current_pointer_position
|
&self.current_pointer_position
|
||||||
}
|
|
||||||
pub fn window(&self) -> Option<Rc<FemtoVGWindow>> {
|
|
||||||
self.window.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layer_surface(&self) -> Option<Rc<ZwlrLayerSurfaceV1>> {
|
pub fn window(&self) -> Rc<FemtoVGWindow> {
|
||||||
self.layer_surface.clone()
|
Rc::clone(&self.window)
|
||||||
}
|
}
|
||||||
pub fn surface(&self) -> Option<Rc<WlSurface>> {
|
|
||||||
self.surface.clone()
|
pub fn layer_surface(&self) -> Rc<ZwlrLayerSurfaceV1> {
|
||||||
|
Rc::clone(&self.layer_surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface(&self) -> Rc<WlSurface> {
|
||||||
|
Rc::clone(&self.surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn height(&self) -> u32 {
|
pub const fn height(&self) -> u32 {
|
||||||
|
@ -125,26 +100,11 @@ impl WindowState {
|
||||||
self.output_size = output_size;
|
self.output_size = output_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn output_size(&self) -> PhysicalSize {
|
pub const fn output_size(&self) -> &PhysicalSize {
|
||||||
self.output_size
|
&self.output_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_window(&mut self, window: Rc<FemtoVGWindow>) {
|
pub const fn component_instance(&self) -> &ComponentInstance {
|
||||||
self.window = Some(window);
|
&self.component_instance
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_layer_surface(&mut self, layer_surface: Rc<ZwlrLayerSurfaceV1>) {
|
|
||||||
self.layer_surface = Some(layer_surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_surface(&mut self, surface: Rc<WlSurface>) {
|
|
||||||
self.surface = Some(surface);
|
|
||||||
}
|
|
||||||
pub fn set_pointer(&mut self, pointer: Rc<WlPointer>) {
|
|
||||||
self.pointer = Some(pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn component_instance(&self) -> Option<&ComponentInstance> {
|
|
||||||
self.component_instance.as_ref()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue