diff --git a/src/windowing/event_handler.rs b/src/windowing/event_handler.rs deleted file mode 100644 index 7c9a449..0000000 --- a/src/windowing/event_handler.rs +++ /dev/null @@ -1,224 +0,0 @@ -use super::state::WindowState; -use crate::impl_empty_dispatch; -use log::info; -use slint::platform::{PointerEventButton, WindowEvent}; -use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{ - zwlr_layer_shell_v1::ZwlrLayerShellV1, - zwlr_layer_surface_v1::{self, ZwlrLayerSurfaceV1}, -}; -use std::rc::Rc; -use std::{cell::RefCell, rc::Weak}; -use wayland_client::WEnum; -use wayland_client::{ - globals::GlobalListContents, - protocol::{ - wl_compositor::WlCompositor, - wl_output::{self, WlOutput}, - wl_pointer::{self, WlPointer}, - wl_registry::WlRegistry, - wl_seat::WlSeat, - wl_surface::WlSurface, - }, - Connection, Dispatch, Proxy, QueueHandle, -}; - -pub struct WindowEventHandler { - state: Weak>, -} - -impl WindowEventHandler { - pub fn new(state: Weak>) -> Self { - Self { state } - } - - pub fn state(&self) -> Rc> { - self.state.upgrade().unwrap() - } - - fn handle_pointer_enter(&self, surface_x: f64, surface_y: f64) { - if let Some(state) = self.state.upgrade() { - state - .borrow_mut() - .set_current_pointer_position(surface_x, surface_y); - if let Some(window) = state.borrow().window() { - let logical_position = state.borrow().current_pointer_position(); - window.dispatch_event(WindowEvent::PointerMoved { - position: logical_position, - }); - } - } - } - - fn handle_pointer_leave(&self) { - if let Some(state) = self.state.upgrade() { - if let Some(window) = state.borrow().window() { - window.dispatch_event(WindowEvent::PointerExited); - } - } - } - - fn handle_pointer_motion(&self, surface_x: f64, surface_y: f64) { - if let Some(state) = self.state.upgrade() { - state - .borrow_mut() - .set_current_pointer_position(surface_x, surface_y); - if let Some(window) = state.borrow().window() { - let logical_position = state.borrow().current_pointer_position(); - window.dispatch_event(WindowEvent::PointerMoved { - position: logical_position, - }); - } - } - } - - fn handle_pointer_button(&self, button_state: wayland_client::WEnum) { - if let Some(state) = self.state.upgrade() { - let is_press = matches!(button_state, WEnum::Value(wl_pointer::ButtonState::Pressed)); - let current_position = state.borrow().current_pointer_position(); - if let Some(window) = state.borrow().window() { - let event = if is_press { - WindowEvent::PointerPressed { - button: PointerEventButton::Left, - position: current_position, - } - } else { - WindowEvent::PointerReleased { - button: PointerEventButton::Left, - position: current_position, - } - }; - window.dispatch_event(event); - } - } - } -} - -impl Dispatch for WindowEventHandler { - fn event( - state: &mut Self, - layer_surface: &ZwlrLayerSurfaceV1, - event: zwlr_layer_surface_v1::Event, - _data: &(), - _conn: &Connection, - _queue_handle: &QueueHandle, - ) { - match event { - zwlr_layer_surface_v1::Event::Configure { - serial, - width, - height, - } => { - info!("Layer surface configured with size: {}x{}", width, height); - layer_surface.ack_configure(serial); - if let Some(state) = state.state.upgrade() { - let state_borrow = state.borrow(); - if width > 0 && height > 0 { - state_borrow - .update_size(state_borrow.output_size().width, state_borrow.height()); - } else { - let current_size = state_borrow.output_size(); - state_borrow.update_size(current_size.width, current_size.height); - } - } - } - zwlr_layer_surface_v1::Event::Closed => { - info!("Layer surface closed"); - } - _ => {} - } - } -} - -impl Dispatch for WindowEventHandler { - fn event( - state: &mut Self, - _proxy: &WlOutput, - event: ::Event, - _data: &(), - _conn: &Connection, - _qhandle: &QueueHandle, - ) { - match event { - wl_output::Event::Mode { width, height, .. } => { - info!("WlOutput size changed to {}x{}", width, height); - if let Some(state) = state.state.upgrade() { - let state_borrow = state.borrow(); - let width = width.try_into().unwrap_or_default(); - let height = height.try_into().unwrap_or_default(); - state_borrow.set_output_size(width, height); - } - } - wl_output::Event::Description { ref description } => { - info!("WlOutput description: {:?}", description); - } - wl_output::Event::Scale { ref factor } => { - info!("WlOutput factor scale: {:?}", factor); - } - wl_output::Event::Name { ref name } => { - info!("WlOutput name: {:?}", name); - } - wl_output::Event::Geometry { - x, - y, - physical_width, - physical_height, - subpixel, - make, - model, - transform, - } => { - info!("WlOutput geometry: x={}, y={}, physical_width={}, physical_height={}, subpixel={:?}, make={:?}, model={:?}, transform={:?}", x, y, physical_width, physical_height, subpixel, make, model, transform); - } - wl_output::Event::Done => { - info!("WlOutput done"); - } - _ => {} - } - } -} - -impl Dispatch for WindowEventHandler { - fn event( - state: &mut Self, - _proxy: &WlPointer, - event: ::Event, - _data: &(), - _conn: &Connection, - _qhandle: &QueueHandle, - ) { - match event { - wl_pointer::Event::Enter { - surface_x, - surface_y, - .. - } => { - state.handle_pointer_enter(surface_x, surface_y); - } - wl_pointer::Event::Leave { .. } => { - state.handle_pointer_leave(); - } - wl_pointer::Event::Motion { - surface_x, - surface_y, - .. - } => { - state.handle_pointer_motion(surface_x, surface_y); - } - wl_pointer::Event::Button { - state: button_state, - .. - } => { - state.handle_pointer_button(button_state); - } - _ => {} - } - } -} - -impl_empty_dispatch!( - (WlRegistry, GlobalListContents), - (WlCompositor, ()), - (WlSurface, ()), - (ZwlrLayerShellV1, ()), - (WlSeat, ()) -); diff --git a/src/windowing/event_loop.rs b/src/windowing/event_loop.rs index 438d76c..fe8d068 100644 --- a/src/windowing/event_loop.rs +++ b/src/windowing/event_loop.rs @@ -6,28 +6,29 @@ use std::rc::{Rc, Weak}; use wayland_client::{Connection, EventQueue}; use crate::rendering::femtovg_window::FemtoVGWindow; -use crate::windowing::event_handler::WindowEventHandler; + +use super::state::WindowState; pub struct EventLoopHandler { window: Weak, - wayland_queue: Weak>>, + wayland_queue: Weak>>, connection: Weak, - event_handler: Weak>, + state: Weak>, } impl EventLoopHandler { pub fn new( window: Weak, - wayland_queue: Weak>>, + wayland_queue: Weak>>, connection: Weak, - event_handler: Weak>, + state: Weak>, ) -> Self { debug!("Creating EventLoopHandler"); Self { window, wayland_queue, connection, - event_handler, + state, } } @@ -35,7 +36,7 @@ impl EventLoopHandler { debug!("Setting up Wayland event source"); let wayland_queue = Weak::clone(&self.wayland_queue); - let event_handler = Weak::clone(&self.event_handler); + let state = Weak::clone(&self.state); let connection = self.connection.upgrade().ok_or_else(|| { anyhow!("Failed to get Wayland connection reference in Wayland event source") })?; @@ -49,18 +50,13 @@ impl EventLoopHandler { let wayland_queue = wayland_queue .upgrade() .ok_or_else(|| anyhow!("Failed to get Wayland queue reference"))?; - let event_handler = event_handler + let state = state .upgrade() .ok_or_else(|| anyhow!("Failed to get event handler reference"))?; let window = window .upgrade() .ok_or_else(|| anyhow!("Failed to get window reference"))?; - Self::handle_wayland_events( - connection, - &wayland_queue, - &event_handler, - &window, - )?; + Self::handle_wayland_events(connection, &wayland_queue, &state, &window)?; Ok(PostAction::Continue) })(); @@ -77,8 +73,8 @@ impl EventLoopHandler { fn handle_wayland_events( connection: &Connection, - wayland_queue: &Rc>>, - event_handler: &Rc>, + wayland_queue: &Rc>>, + state: &Rc>, window: &Rc, ) -> Result<()> { connection @@ -93,7 +89,7 @@ impl EventLoopHandler { } event_queue - .dispatch_pending(&mut *event_handler.borrow_mut()) + .dispatch_pending(&mut *state.borrow_mut()) .map_err(|e| anyhow!("Failed to dispatch Wayland events: {}", e))?; slint::platform::update_timers_and_animations(); diff --git a/src/windowing/macros.rs b/src/windowing/macros.rs index c19bdde..80174a0 100644 --- a/src/windowing/macros.rs +++ b/src/windowing/macros.rs @@ -2,7 +2,7 @@ macro_rules! impl_empty_dispatch { ($(($t:ty, $u:ty)),+) => { $( - impl Dispatch<$t, $u> for WindowEventHandler { + impl Dispatch<$t, $u> for WindowState { fn event( _state: &mut Self, _proxy: &$t, diff --git a/src/windowing/mod.rs b/src/windowing/mod.rs index 7c54191..3509989 100644 --- a/src/windowing/mod.rs +++ b/src/windowing/mod.rs @@ -1,4 +1,4 @@ -use self::{event_handler::WindowEventHandler, event_loop::EventLoopHandler, state::WindowState}; +use self::{event_loop::EventLoopHandler, state::WindowState}; use crate::{ bind_globals, rendering::{ @@ -29,7 +29,6 @@ use wayland_client::{ Connection, EventQueue, Proxy, QueueHandle, }; -mod event_handler; mod event_loop; mod macros; mod state; @@ -150,9 +149,8 @@ impl WindowingSystemBuilder { pub struct WindowingSystem<'a> { state: Rc>, connection: Rc, - event_handler: Rc>, window: Option>, - event_queue: Rc>>, + event_queue: Rc>>, component_instance: Option>, display: WlDisplay, config: WindowConfig, @@ -165,7 +163,6 @@ impl<'a> WindowingSystem<'a> { info!("Initializing WindowingSystem"); let connection = Rc::new(Connection::connect_to_env()?); let state = Rc::new(RefCell::new(WindowState::new(&config))); - let event_handler = Rc::new(RefCell::new(WindowEventHandler::new(Rc::downgrade(&state)))); let display = connection.display(); let event_queue = Rc::new(RefCell::new(connection.new_event_queue())); let global_list = Self::initialize_registry(&connection)?; @@ -178,7 +175,7 @@ impl<'a> WindowingSystem<'a> { &layer_shell, &seat, &event_queue.borrow().handle(), - &event_handler, + &state, &config, ); @@ -187,7 +184,6 @@ impl<'a> WindowingSystem<'a> { let mut system = Self { state, connection, - event_handler, window: None, event_queue, component_instance: None, @@ -199,21 +195,19 @@ impl<'a> WindowingSystem<'a> { system.wait_for_configure()?; system.initialize_renderer_and_ui()?; - system.initialize_event_loop_handler(); - system.setup_event_sources()?; Ok(system) } fn initialize_registry(connection: &Connection) -> Result { - registry_queue_init::(connection) + registry_queue_init::(connection) .map(|(global_list, _)| global_list) .context("Failed to initialize registry") } fn bind_globals( global_list: &GlobalList, - queue_handle: &QueueHandle, + queue_handle: &QueueHandle, ) -> Result<(WlCompositor, WlOutput, ZwlrLayerShellV1, WlSeat)> { bind_globals!( global_list, @@ -230,8 +224,8 @@ impl<'a> WindowingSystem<'a> { output: &WlOutput, layer_shell: &ZwlrLayerShellV1, seat: &WlSeat, - queue_handle: &QueueHandle, - event_handler: &Rc>, + queue_handle: &QueueHandle, + state: &Rc>, config: &WindowConfig, ) { let surface = Rc::new(compositor.create_surface(queue_handle, ())); @@ -246,9 +240,7 @@ impl<'a> WindowingSystem<'a> { let pointer = Rc::new(seat.get_pointer(queue_handle, ())); - let binding = event_handler.borrow_mut(); - let binding = binding.state(); - let mut state = binding.borrow_mut(); + let mut state = state.borrow_mut(); state.set_surface(Rc::clone(&surface)); state.set_layer_surface(Rc::clone(&layer_surface)); state.set_pointer(pointer); @@ -277,19 +269,17 @@ impl<'a> WindowingSystem<'a> { fn wait_for_configure(&self) -> Result<()> { info!("Waiting for surface to be configured..."); - loop { - self.connection.flush()?; - self.event_queue - .borrow_mut() - .blocking_dispatch(&mut self.event_handler.borrow_mut()) - .context("Failed to dispatch events")?; - - let state = self.state.borrow(); - let size = state.output_size(); - if size.width > 1 && size.height > 1 { - info!("Configured output size: {:?}", size); - break; - } + let mut state = self.state.borrow_mut(); + self.event_queue + .borrow_mut() + .blocking_dispatch(&mut state) + .context("Failed to dispatch events")?; + 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(()) @@ -361,7 +351,7 @@ impl<'a> WindowingSystem<'a> { Rc::downgrade(self.window.as_ref().unwrap()), Rc::downgrade(&self.event_queue), Rc::downgrade(&self.connection), - Rc::downgrade(&self.event_handler), + Rc::downgrade(&self.state), ); self.event_loop_handler = Some(event_loop_handler); @@ -385,6 +375,8 @@ impl<'a> WindowingSystem<'a> { pub fn run(&mut self) -> Result<()> { info!("Starting WindowingSystem main loop"); + self.initialize_event_loop_handler(); + self.setup_event_sources()?; if let Some(window) = &self.window { window.render_frame_if_dirty(); } diff --git a/src/windowing/state/dispatches.rs b/src/windowing/state/dispatches.rs new file mode 100644 index 0000000..3c88f1a --- /dev/null +++ b/src/windowing/state/dispatches.rs @@ -0,0 +1,175 @@ +use crate::impl_empty_dispatch; +use log::info; +use slint::platform::{PointerEventButton, WindowEvent}; +use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{ + zwlr_layer_shell_v1::ZwlrLayerShellV1, + zwlr_layer_surface_v1::{self, ZwlrLayerSurfaceV1}, +}; +use wayland_client::WEnum; +use wayland_client::{ + globals::GlobalListContents, + protocol::{ + wl_compositor::WlCompositor, + wl_output::{self, WlOutput}, + wl_pointer::{self, WlPointer}, + wl_registry::WlRegistry, + wl_seat::WlSeat, + wl_surface::WlSurface, + }, + Connection, Dispatch, Proxy, QueueHandle, +}; + +use super::WindowState; + +impl Dispatch for WindowState { + fn event( + state: &mut Self, + layer_surface: &ZwlrLayerSurfaceV1, + event: zwlr_layer_surface_v1::Event, + _data: &(), + _conn: &Connection, + _queue_handle: &QueueHandle, + ) { + match event { + zwlr_layer_surface_v1::Event::Configure { + serial, + width, + height, + } => { + info!("Layer surface configured with size: {}x{}", width, height); + layer_surface.ack_configure(serial); + if width > 0 && height > 0 { + state.update_size(state.output_size().width, state.height()); + } else { + let current_size = state.output_size(); + state.update_size(current_size.width, current_size.height); + } + } + zwlr_layer_surface_v1::Event::Closed => { + info!("Layer surface closed"); + } + _ => {} + } + } +} + +impl Dispatch for WindowState { + fn event( + state: &mut Self, + _proxy: &WlOutput, + event: ::Event, + _data: &(), + _conn: &Connection, + _qhandle: &QueueHandle, + ) { + match event { + wl_output::Event::Mode { width, height, .. } => { + info!("WlOutput size changed to {}x{}", width, height); + let width = width.try_into().unwrap_or_default(); + let height = height.try_into().unwrap_or_default(); + state.set_output_size(width, height); + } + wl_output::Event::Description { ref description } => { + info!("WlOutput description: {:?}", description); + } + wl_output::Event::Scale { ref factor } => { + info!("WlOutput factor scale: {:?}", factor); + } + wl_output::Event::Name { ref name } => { + info!("WlOutput name: {:?}", name); + } + wl_output::Event::Geometry { + x, + y, + physical_width, + physical_height, + subpixel, + make, + model, + transform, + } => { + info!("WlOutput geometry: x={}, y={}, physical_width={}, physical_height={}, subpixel={:?}, make={:?}, model={:?}, transform={:?}", x, y, physical_width, physical_height, subpixel, make, model, transform); + } + wl_output::Event::Done => { + info!("WlOutput done"); + } + _ => {} + } + } +} + +impl Dispatch for WindowState { + fn event( + state: &mut Self, + _proxy: &WlPointer, + event: ::Event, + _data: &(), + _conn: &Connection, + _qhandle: &QueueHandle, + ) { + match event { + wl_pointer::Event::Enter { + surface_x, + 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::Leave { .. } => { + if let Some(window) = state.window() { + window.dispatch_event(WindowEvent::PointerExited); + } + } + wl_pointer::Event::Motion { + 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(); + window.dispatch_event(WindowEvent::PointerMoved { + position: logical_position, + }); + } + } + wl_pointer::Event::Button { + state: button_state, + .. + } => { + let is_press = + matches!(button_state, WEnum::Value(wl_pointer::ButtonState::Pressed)); + let current_position = state.current_pointer_position(); + if let Some(window) = state.window() { + let event = if is_press { + WindowEvent::PointerPressed { + button: PointerEventButton::Left, + position: current_position, + } + } else { + WindowEvent::PointerReleased { + button: PointerEventButton::Left, + position: current_position, + } + }; + window.dispatch_event(event); + } + } + _ => {} + } + } +} + +impl_empty_dispatch!( + (WlRegistry, GlobalListContents), + (WlCompositor, ()), + (WlSurface, ()), + (ZwlrLayerShellV1, ()), + (WlSeat, ()) +); diff --git a/src/windowing/state.rs b/src/windowing/state/mod.rs similarity index 92% rename from src/windowing/state.rs rename to src/windowing/state/mod.rs index 9c3ed95..3d6ea17 100644 --- a/src/windowing/state.rs +++ b/src/windowing/state/mod.rs @@ -5,13 +5,14 @@ use slint::{LogicalPosition, PhysicalSize}; 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; - use super::WindowConfig; +pub mod dispatches; + pub struct WindowState { surface: Option>, layer_surface: Option>, - size: Cell, + size: PhysicalSize, output_size: Cell, pointer: Option>, window: Option>, @@ -26,7 +27,7 @@ impl WindowState { Self { surface: None, layer_surface: None, - size: Cell::new(PhysicalSize::default()), + size: PhysicalSize::default(), output_size: Cell::new(PhysicalSize::default()), pointer: None, window: None, @@ -37,9 +38,8 @@ impl WindowState { } } - pub fn update_size(&self, width: u32, height: u32) { + pub fn update_size(&mut self, width: u32, height: u32) { let new_size = PhysicalSize::new(width, height); - self.size.set(new_size); if let Some(window) = &self.window() { info!("Updating window size to {}x{}", width, height); window.set_size(slint::WindowSize::Physical(new_size)); @@ -55,6 +55,7 @@ impl WindowState { if let Some(s) = self.surface.as_ref() { s.commit(); } + self.size = new_size; } pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) { @@ -67,12 +68,12 @@ impl WindowState { } pub fn size(&self) -> PhysicalSize { - self.size.get() + self.size } pub fn output_size(&self) -> PhysicalSize { self.output_size.get() } - pub fn current_pointer_position(&self) -> LogicalPosition { + pub const fn current_pointer_position(&self) -> LogicalPosition { self.current_pointer_position } pub fn window(&self) -> Option> {