diff --git a/adapters/src/wayland/shell_adapter.rs b/adapters/src/wayland/shell_adapter.rs index ccdb346..63285f4 100644 --- a/adapters/src/wayland/shell_adapter.rs +++ b/adapters/src/wayland/shell_adapter.rs @@ -5,7 +5,7 @@ use crate::wayland::{ surfaces::layer_surface::{SurfaceCtx, SurfaceSetupParams}, surfaces::popup_manager::{CreatePopupParams, PopupContext, PopupManager}, surfaces::{ - scale_coordinator::SharedPointerSerial, surface_builder::WindowStateBuilder, + event_context::SharedPointerSerial, surface_builder::WindowStateBuilder, surface_state::WindowState, }, }; diff --git a/adapters/src/wayland/surfaces/event_context.rs b/adapters/src/wayland/surfaces/event_context.rs new file mode 100644 index 0000000..40ef62f --- /dev/null +++ b/adapters/src/wayland/surfaces/event_context.rs @@ -0,0 +1,203 @@ +use crate::rendering::femtovg::main_window::FemtoVGWindow; +use crate::wayland::services::popup_service::{ActiveWindow, PopupService}; +use crate::wayland::surfaces::event_bus::EventBus; +use crate::wayland::surfaces::popup_manager::PopupManager; +use crate::wayland::surfaces::window_events::{ScaleSource, WindowStateEvent}; +use layer_shika_domain::value_objects::popup_request::PopupHandle; +use log::info; +use slint::platform::{WindowAdapter, WindowEvent}; +use slint::{LogicalPosition, PhysicalSize}; +use std::cell::Cell; +use std::rc::Rc; +use wayland_client::{backend::ObjectId, protocol::wl_surface::WlSurface}; +use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1; + +pub struct SharedPointerSerial { + serial: Cell, +} + +impl Default for SharedPointerSerial { + fn default() -> Self { + Self::new() + } +} + +impl SharedPointerSerial { + pub const fn new() -> Self { + Self { + serial: Cell::new(0), + } + } + + pub fn update(&self, serial: u32) { + self.serial.set(serial); + } + + pub fn get(&self) -> u32 { + self.serial.get() + } +} + +pub struct EventContext { + main_window: Rc, + main_surface_id: ObjectId, + popup_service: Option>, + event_bus: EventBus, + scale_factor: f32, + has_fractional_scale: bool, + current_pointer_position: LogicalPosition, + last_pointer_serial: u32, + shared_pointer_serial: Option>, +} + +impl EventContext { + #[must_use] + pub fn new( + main_window: Rc, + main_surface_id: ObjectId, + scale_factor: f32, + has_fractional_scale: bool, + ) -> Self { + Self { + main_window, + main_surface_id, + popup_service: None, + event_bus: EventBus::new(), + scale_factor, + has_fractional_scale, + current_pointer_position: LogicalPosition::new(0.0, 0.0), + last_pointer_serial: 0, + shared_pointer_serial: None, + } + } + + pub fn set_event_bus(&mut self, event_bus: EventBus) { + self.event_bus = event_bus; + } + + pub const fn event_bus(&self) -> &EventBus { + &self.event_bus + } + + pub fn set_popup_service(&mut self, popup_service: Rc) { + self.popup_service = Some(popup_service); + self.event_bus + .publish(&WindowStateEvent::PopupConfigurationChanged); + } + + pub const fn popup_service(&self) -> &Option> { + &self.popup_service + } + + pub fn popup_manager(&self) -> Option> { + self.popup_service + .as_ref() + .map(|service| Rc::clone(service.manager())) + } + + pub const fn scale_factor(&self) -> f32 { + self.scale_factor + } + + #[allow(clippy::cast_precision_loss)] + pub fn update_scale_factor(&mut self, scale_120ths: u32) -> f32 { + let new_scale_factor = scale_120ths as f32 / 120.0; + let old_scale_factor = self.scale_factor; + info!( + "Updating scale factor from {} to {} ({}x)", + old_scale_factor, new_scale_factor, scale_120ths + ); + self.scale_factor = new_scale_factor; + + if let Some(popup_service) = &self.popup_service { + popup_service.update_scale_factor(new_scale_factor); + } + + self.event_bus + .publish(&WindowStateEvent::ScaleFactorChanged { + new_scale: new_scale_factor, + source: ScaleSource::FractionalScale, + }); + + new_scale_factor + } + + pub const fn current_pointer_position(&self) -> LogicalPosition { + self.current_pointer_position + } + + #[allow(clippy::cast_possible_truncation)] + pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) { + let logical_position = if self.has_fractional_scale { + LogicalPosition::new(physical_x as f32, physical_y as f32) + } else { + LogicalPosition::new( + (physical_x / f64::from(self.scale_factor)) as f32, + (physical_y / f64::from(self.scale_factor)) as f32, + ) + }; + self.current_pointer_position = logical_position; + + self.event_bus + .publish(&WindowStateEvent::PointerPositionChanged { + physical_x, + physical_y, + }); + } + + pub const fn last_pointer_serial(&self) -> u32 { + self.last_pointer_serial + } + + pub fn set_last_pointer_serial(&mut self, serial: u32) { + self.last_pointer_serial = serial; + if let Some(ref shared_serial) = self.shared_pointer_serial { + shared_serial.update(serial); + } + + self.event_bus + .publish(&WindowStateEvent::PointerSerialUpdated { serial }); + } + + pub fn set_shared_pointer_serial(&mut self, shared_serial: Rc) { + self.shared_pointer_serial = Some(shared_serial); + } + + pub fn dispatch_to_active_window(&self, event: WindowEvent, surface: &WlSurface) { + if let Some(popup_service) = &self.popup_service { + match popup_service.get_active_window(surface, &self.main_surface_id) { + ActiveWindow::Main => { + self.main_window.window().dispatch_event(event); + } + ActiveWindow::Popup(index) => { + if let Some(popup_window) = + popup_service.get_popup_window(PopupHandle::new(index)) + { + popup_window.dispatch_event(event); + } + } + ActiveWindow::None => {} + } + } + } + + pub fn update_output_size(&self, output_size: PhysicalSize) { + if let Some(popup_service) = &self.popup_service { + popup_service.update_output_size(output_size); + } + + self.event_bus + .publish(&WindowStateEvent::OutputSizeChanged { output_size }); + } + + pub fn update_scale_for_fractional_scale_object( + &self, + fractional_scale_proxy: &WpFractionalScaleV1, + scale_120ths: u32, + ) { + if let Some(popup_service) = &self.popup_service { + popup_service + .update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths); + } + } +} diff --git a/adapters/src/wayland/surfaces/interaction_state.rs b/adapters/src/wayland/surfaces/interaction_state.rs deleted file mode 100644 index 1e666b8..0000000 --- a/adapters/src/wayland/surfaces/interaction_state.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::wayland::managed_proxies::ManagedWlPointer; -use crate::wayland::services::popup_service::PopupService; -use crate::wayland::surfaces::event_bus::EventBus; -use crate::wayland::surfaces::event_router::EventRouter; -use crate::wayland::surfaces::scale_coordinator::{ScaleCoordinator, SharedPointerSerial}; -use crate::wayland::surfaces::window_events::{ScaleSource, WindowStateEvent}; -use slint::LogicalPosition; -use slint::platform::WindowEvent; -use std::rc::Rc; -use wayland_client::protocol::wl_surface::WlSurface; - -pub struct InteractionState { - #[allow(dead_code)] - pointer: ManagedWlPointer, - event_router: EventRouter, - scale_coordinator: ScaleCoordinator, - event_bus: EventBus, -} - -impl InteractionState { - #[must_use] - pub fn new( - pointer: ManagedWlPointer, - event_router: EventRouter, - scale_coordinator: ScaleCoordinator, - ) -> Self { - Self { - pointer, - event_router, - scale_coordinator, - event_bus: EventBus::new(), - } - } - - pub fn set_event_bus(&mut self, event_bus: EventBus) { - self.event_bus = event_bus; - } - - #[allow(clippy::cast_possible_truncation)] - pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) { - self.scale_coordinator - .set_current_pointer_position(physical_x, physical_y); - - self.event_bus - .publish(&WindowStateEvent::PointerPositionChanged { - physical_x, - physical_y, - }); - } - - pub fn current_pointer_position(&self) -> LogicalPosition { - self.scale_coordinator.current_pointer_position() - } - - pub fn last_pointer_serial(&self) -> u32 { - self.scale_coordinator.last_pointer_serial() - } - - pub fn set_last_pointer_serial(&mut self, serial: u32) { - self.scale_coordinator.set_last_pointer_serial(serial); - - self.event_bus - .publish(&WindowStateEvent::PointerSerialUpdated { serial }); - } - - pub fn set_shared_pointer_serial(&mut self, shared_serial: Rc) { - self.scale_coordinator - .set_shared_pointer_serial(shared_serial); - } - - pub fn set_popup_service(&mut self, popup_service: Rc) { - self.event_router.set_popup_service(popup_service); - } - - pub fn dispatch_to_active_window(&self, event: WindowEvent, surface: &WlSurface) { - self.event_router.dispatch_to_active_window(event, surface); - } - - pub fn scale_factor(&self) -> f32 { - self.scale_coordinator.scale_factor() - } - - #[allow(clippy::cast_precision_loss)] - pub fn update_scale_factor(&mut self, scale_120ths: u32) -> f32 { - let new_scale = self.scale_coordinator.update_scale_factor(scale_120ths); - - self.event_bus - .publish(&WindowStateEvent::ScaleFactorChanged { - new_scale, - source: ScaleSource::FractionalScale, - }); - - new_scale - } -} diff --git a/adapters/src/wayland/surfaces/mod.rs b/adapters/src/wayland/surfaces/mod.rs index fb1fe31..f76309e 100644 --- a/adapters/src/wayland/surfaces/mod.rs +++ b/adapters/src/wayland/surfaces/mod.rs @@ -1,14 +1,13 @@ pub mod component_state; pub mod dimensions; pub mod event_bus; +pub mod event_context; pub mod event_router; -pub mod interaction_state; pub mod layer_surface; pub mod popup_manager; pub mod popup_state; pub mod popup_surface; pub mod rendering_state; -pub mod scale_coordinator; pub mod surface_builder; pub mod surface_state; pub mod window_events; diff --git a/adapters/src/wayland/surfaces/rendering_state.rs b/adapters/src/wayland/surfaces/rendering_state.rs index c6a3843..91f9335 100644 --- a/adapters/src/wayland/surfaces/rendering_state.rs +++ b/adapters/src/wayland/surfaces/rendering_state.rs @@ -2,15 +2,12 @@ use std::rc::Rc; use crate::errors::Result; use crate::rendering::femtovg::main_window::FemtoVGWindow; use crate::wayland::surfaces::window_renderer::{WindowRenderer, WindowRendererParams}; -use crate::wayland::surfaces::event_bus::EventBus; -use crate::wayland::surfaces::window_events::WindowStateEvent; 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, - event_bus: EventBus, } impl RenderingState { @@ -18,25 +15,15 @@ impl RenderingState { pub fn new(params: WindowRendererParams) -> Self { Self { renderer: WindowRenderer::new(params), - event_bus: EventBus::new(), } } - pub fn set_event_bus(&mut self, event_bus: EventBus) { - self.event_bus = event_bus; - } - pub fn render_frame_if_dirty(&self) -> Result<()> { self.renderer.render_frame_if_dirty() } pub fn update_size(&mut self, width: u32, height: u32, scale_factor: f32) { self.renderer.update_size(width, height, scale_factor); - - self.event_bus.publish(&WindowStateEvent::SizeChanged { - logical_width: width, - logical_height: height, - }); } pub const fn size(&self) -> PhysicalSize { diff --git a/adapters/src/wayland/surfaces/scale_coordinator.rs b/adapters/src/wayland/surfaces/scale_coordinator.rs deleted file mode 100644 index f1dfa4e..0000000 --- a/adapters/src/wayland/surfaces/scale_coordinator.rs +++ /dev/null @@ -1,99 +0,0 @@ -use log::info; -use slint::LogicalPosition; -use std::cell::Cell; -use std::rc::Rc; - -pub struct SharedPointerSerial { - serial: Cell, -} - -impl Default for SharedPointerSerial { - fn default() -> Self { - Self::new() - } -} - -impl SharedPointerSerial { - pub const fn new() -> Self { - Self { - serial: Cell::new(0), - } - } - - pub fn update(&self, serial: u32) { - self.serial.set(serial); - } - - pub fn get(&self) -> u32 { - self.serial.get() - } -} - -pub struct ScaleCoordinator { - scale_factor: f32, - current_pointer_position: LogicalPosition, - last_pointer_serial: u32, - shared_pointer_serial: Option>, - has_fractional_scale: bool, -} - -impl ScaleCoordinator { - #[must_use] - pub const fn new(scale_factor: f32, has_fractional_scale: bool) -> Self { - Self { - scale_factor, - current_pointer_position: LogicalPosition::new(0.0, 0.0), - last_pointer_serial: 0, - shared_pointer_serial: None, - has_fractional_scale, - } - } - - pub const fn scale_factor(&self) -> f32 { - self.scale_factor - } - - #[allow(clippy::cast_precision_loss)] - pub fn update_scale_factor(&mut self, scale_120ths: u32) -> f32 { - let new_scale_factor = scale_120ths as f32 / 120.0; - let old_scale_factor = self.scale_factor; - info!( - "Updating scale factor from {} to {} ({}x)", - old_scale_factor, new_scale_factor, scale_120ths - ); - self.scale_factor = new_scale_factor; - new_scale_factor - } - - #[allow(clippy::cast_possible_truncation)] - pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) { - let logical_position = if self.has_fractional_scale { - LogicalPosition::new(physical_x as f32, physical_y as f32) - } else { - LogicalPosition::new( - (physical_x / f64::from(self.scale_factor)) as f32, - (physical_y / f64::from(self.scale_factor)) as f32, - ) - }; - self.current_pointer_position = logical_position; - } - - pub const fn current_pointer_position(&self) -> LogicalPosition { - self.current_pointer_position - } - - pub const fn last_pointer_serial(&self) -> u32 { - self.last_pointer_serial - } - - pub fn set_last_pointer_serial(&mut self, serial: u32) { - self.last_pointer_serial = serial; - if let Some(ref shared_serial) = self.shared_pointer_serial { - shared_serial.update(serial); - } - } - - pub fn set_shared_pointer_serial(&mut self, shared_serial: Rc) { - self.shared_pointer_serial = Some(shared_serial); - } -} diff --git a/adapters/src/wayland/surfaces/surface_state.rs b/adapters/src/wayland/surfaces/surface_state.rs index 5b90d15..4dc45a3 100644 --- a/adapters/src/wayland/surfaces/surface_state.rs +++ b/adapters/src/wayland/surfaces/surface_state.rs @@ -3,13 +3,9 @@ use std::cell::RefCell; use super::surface_builder::WindowStateBuilder; use super::component_state::ComponentState; use super::rendering_state::RenderingState; -use super::interaction_state::InteractionState; -use super::event_router::EventRouter; -use super::popup_state::PopupState; +use super::event_context::{EventContext, SharedPointerSerial}; use super::popup_manager::PopupManager; -use super::scale_coordinator::{ScaleCoordinator, SharedPointerSerial}; use super::window_renderer::WindowRendererParams; -use super::event_bus::EventBus; use crate::wayland::managed_proxies::{ ManagedWlPointer, ManagedWlSurface, ManagedZwlrLayerSurfaceV1, ManagedWpFractionalScaleV1, ManagedWpViewport, @@ -31,13 +27,12 @@ use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1: pub struct WindowState { component: ComponentState, rendering: RenderingState, - interaction: InteractionState, - popup: PopupState, + event_context: EventContext, + #[allow(dead_code)] + pointer: ManagedWlPointer, output_size: PhysicalSize, active_popup_key: RefCell>, main_surface: Rc, - #[allow(dead_code)] - event_bus: EventBus, } impl WindowState { @@ -95,20 +90,14 @@ impl WindowState { let size = builder.size.unwrap_or_default(); let main_surface_id = (*surface_rc).id(); - let event_router = EventRouter::new(Rc::clone(&window), main_surface_id); - let scale_coordinator = ScaleCoordinator::new(builder.scale_factor, has_fractional_scale); + let event_context = EventContext::new( + Rc::clone(&window), + main_surface_id, + builder.scale_factor, + has_fractional_scale, + ); - let mut interaction = InteractionState::new(pointer, event_router, scale_coordinator); - - let mut popup = PopupState::new(); - - let event_bus = EventBus::new(); - - let event_bus_clone_for_rendering = event_bus.clone(); - let event_bus_clone_for_interaction = event_bus.clone(); - let event_bus_clone_for_popup = event_bus.clone(); - - let mut rendering = RenderingState::new(WindowRendererParams { + let rendering = RenderingState::new(WindowRendererParams { window: Rc::clone(&window), surface, layer_surface, @@ -119,37 +108,25 @@ impl WindowState { size, }); - rendering.set_event_bus(event_bus_clone_for_rendering); - interaction.set_event_bus(event_bus_clone_for_interaction); - popup.set_event_bus(event_bus_clone_for_popup); - - let mut instance = Self { + Ok(Self { component, rendering, - interaction, - popup, + event_context, + pointer, output_size: builder.output_size.unwrap_or_default(), active_popup_key: RefCell::new(None), main_surface: surface_rc, - event_bus, - }; - - instance.setup_event_handlers(); - - Ok(instance) + }) } - #[allow(clippy::unused_self)] - fn setup_event_handlers(&mut self) {} - pub fn update_size(&mut self, width: u32, height: u32) { - let scale_factor = self.interaction.scale_factor(); + let scale_factor = self.event_context.scale_factor(); self.rendering.update_size(width, height, scale_factor); } #[allow(clippy::cast_possible_truncation)] pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) { - self.interaction + self.event_context .set_current_pointer_position(physical_x, physical_y); } @@ -158,7 +135,7 @@ impl WindowState { } pub fn current_pointer_position(&self) -> LogicalPosition { - self.interaction.current_pointer_position() + self.event_context.current_pointer_position() } pub(crate) fn window(&self) -> Rc { @@ -175,7 +152,7 @@ impl WindowState { pub fn set_output_size(&mut self, output_size: PhysicalSize) { self.output_size = output_size; - self.popup.update_output_size(output_size); + self.event_context.update_output_size(output_size); } pub const fn output_size(&self) -> PhysicalSize { @@ -197,9 +174,7 @@ impl WindowState { #[allow(clippy::cast_precision_loss)] pub fn update_scale_factor(&mut self, scale_120ths: u32) { - let new_scale_factor = self.interaction.update_scale_factor(scale_120ths); - - self.popup.update_scale_factor(new_scale_factor); + self.event_context.update_scale_factor(scale_120ths); let current_logical_size = self.rendering.logical_size(); if current_logical_size.width > 0 && current_logical_size.height > 0 { @@ -208,33 +183,32 @@ impl WindowState { } pub fn scale_factor(&self) -> f32 { - self.interaction.scale_factor() + self.event_context.scale_factor() } pub fn last_pointer_serial(&self) -> u32 { - self.interaction.last_pointer_serial() + self.event_context.last_pointer_serial() } pub fn set_last_pointer_serial(&mut self, serial: u32) { - self.interaction.set_last_pointer_serial(serial); + self.event_context.set_last_pointer_serial(serial); } pub fn set_shared_pointer_serial(&mut self, shared_serial: Rc) { - self.interaction.set_shared_pointer_serial(shared_serial); + self.event_context.set_shared_pointer_serial(shared_serial); } pub fn set_popup_service(&mut self, popup_service: Rc) { - self.interaction - .set_popup_service(Rc::clone(&popup_service)); - self.popup.set_popup_service(popup_service); + self.event_context.set_popup_service(popup_service); } pub fn set_popup_manager(&mut self, popup_manager: Rc) { - self.popup.set_popup_manager(popup_manager); + let popup_service = Rc::new(PopupService::new(popup_manager)); + self.event_context.set_popup_service(popup_service); } pub fn set_entered_surface(&self, surface: &WlSurface) { - if let Some(popup_service) = self.popup.popup_service() { + if let Some(popup_service) = self.event_context.popup_service() { if let Some(popup_key) = popup_service .manager() .find_popup_key_by_surface_id(&surface.id()) @@ -254,7 +228,7 @@ impl WindowState { let active_popup = *self.active_popup_key.borrow(); if let Some(popup_key) = active_popup { - if let Some(popup_service) = self.popup.popup_service() { + if let Some(popup_service) = self.event_context.popup_service() { if let Some(popup_window) = popup_service.get_popup_window(PopupHandle::new(popup_key)) { @@ -264,7 +238,7 @@ impl WindowState { } } - self.interaction + self.event_context .dispatch_to_active_window(event, &self.main_surface); } @@ -283,16 +257,16 @@ impl WindowState { } } - self.popup + self.event_context .update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths); } pub fn popup_service(&self) -> &Option> { - self.popup.popup_service() + self.event_context.popup_service() } pub fn popup_manager(&self) -> Option> { - self.popup.popup_manager() + self.event_context.popup_manager() } }