diff --git a/crates/adapters/src/wayland/shell_adapter.rs b/crates/adapters/src/wayland/shell_adapter.rs index 1ff0e40..6cc45e0 100644 --- a/crates/adapters/src/wayland/shell_adapter.rs +++ b/crates/adapters/src/wayland/shell_adapter.rs @@ -2,7 +2,7 @@ use crate::wayland::{ config::{LayerSurfaceParams, WaylandWindowConfig}, globals::context::GlobalContext, surfaces::layer_surface::{SurfaceCtx, SurfaceSetupParams}, - surfaces::popup_manager::{CreatePopupParams, PopupContext, PopupManager}, + surfaces::popup_manager::{PopupContext, PopupManager}, surfaces::{ event_context::SharedPointerSerial, surface_builder::WindowStateBuilder, surface_state::WindowState, @@ -183,38 +183,8 @@ impl WaylandWindowingSystem { let serial = serial_holder.get(); - let (params, request) = if let Some((request, width, height)) = - popup_manager_clone.take_pending_popup() - { - log::info!( - "Using popup request: component='{}', position=({}, {}), size={}x{}, mode={:?}", - request.component, - request.at.position().0, - request.at.position().1, - width, - height, - request.mode - ); - - let params = CreatePopupParams { - last_pointer_serial: serial, - reference_x: request.at.position().0, - reference_y: request.at.position().1, - width, - height, - positioning_mode: request.mode, - }; - (params, request) - } else { - log::warn!("Popup creator called without pending popup request - aborting"); - return Err(PlatformError::Other( - "No popup request available - cannot create popup without parameters" - .to_string(), - )); - }; - let popup_window = popup_manager_clone - .create_popup(&queue_handle, &layer_surface, params, request) + .create_pending_popup(&queue_handle, &layer_surface, serial) .map_err(|e| PlatformError::Other(format!("Failed to create popup: {e}")))?; let result = Ok(popup_window as Rc); diff --git a/crates/adapters/src/wayland/surfaces/popup_manager.rs b/crates/adapters/src/wayland/surfaces/popup_manager.rs index 95ae1f3..babd6ca 100644 --- a/crates/adapters/src/wayland/surfaces/popup_manager.rs +++ b/crates/adapters/src/wayland/surfaces/popup_manager.rs @@ -34,7 +34,7 @@ pub enum ActiveWindow { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -struct PopupId(usize); +pub(crate) struct PopupId(usize); impl PopupId { #[must_use] @@ -110,6 +110,7 @@ impl Drop for ActivePopup { } struct PendingPopup { + id: PopupId, request: PopupRequest, width: f32, height: f32, @@ -133,6 +134,12 @@ impl PopupManagerState { id_generator: 0, } } + + fn allocate_id(&mut self) -> PopupId { + let id = PopupId(self.id_generator); + self.id_generator += 1; + id + } } pub struct PopupManager { @@ -152,21 +159,28 @@ impl PopupManager { } } - pub fn set_pending_popup(&self, request: PopupRequest, width: f32, height: f32) { - self.state.borrow_mut().pending_popup = Some(PendingPopup { + pub fn request_popup(&self, request: PopupRequest, width: f32, height: f32) -> PopupHandle { + let mut state = self.state.borrow_mut(); + + let id = state.allocate_id(); + + state.pending_popup = Some(PendingPopup { + id, request, width, height, }); + + id.to_handle() } #[must_use] - pub fn take_pending_popup(&self) -> Option<(PopupRequest, f32, f32)> { + pub(crate) fn take_pending_popup_params(&self) -> Option<(PopupId, PopupRequest, f32, f32)> { self.state .borrow_mut() .pending_popup .take() - .map(|p| (p.request, p.width, p.height)) + .map(|p| (p.id, p.request, p.width, p.height)) } #[must_use] @@ -208,12 +222,37 @@ impl PopupManager { self.state.borrow().current_popup_id.map(PopupId::key) } - pub fn create_popup( + pub fn create_pending_popup( + self: &Rc, + queue_handle: &QueueHandle, + parent_layer_surface: &ZwlrLayerSurfaceV1, + last_pointer_serial: u32, + ) -> Result> { + let (id, request, width, height) = self.take_pending_popup_params().ok_or_else(|| { + LayerShikaError::WindowConfiguration { + message: "No pending popup request available".into(), + } + })?; + + let params = CreatePopupParams { + last_pointer_serial, + reference_x: request.at.position().0, + reference_y: request.at.position().1, + width, + height, + positioning_mode: request.mode, + }; + + self.create_popup_internal(queue_handle, parent_layer_surface, params, request, id) + } + + fn create_popup_internal( self: &Rc, queue_handle: &QueueHandle, parent_layer_surface: &ZwlrLayerSurfaceV1, params: CreatePopupParams, request: PopupRequest, + popup_id: PopupId, ) -> Result> { let xdg_wm_base = self.context.xdg_wm_base.as_ref().ok_or_else(|| { LayerShikaError::WindowConfiguration { @@ -285,13 +324,6 @@ impl PopupManager { let renderer = FemtoVGRenderer::new(context) .map_err(|e| LayerShikaError::FemtoVGRendererCreation { source: e })?; - let popup_id = { - let mut state = self.state.borrow_mut(); - let id = PopupId(state.id_generator); - state.id_generator += 1; - id - }; - let on_close: OnCloseCallback = { let weak_self = Rc::downgrade(self); Box::new(move |handle: PopupHandle| { @@ -422,8 +454,8 @@ impl PopupManager { } } - pub fn show(&self, request: PopupRequest, width: f32, height: f32) { - self.set_pending_popup(request, width, height); + pub fn show(&self, request: PopupRequest, width: f32, height: f32) -> PopupHandle { + self.request_popup(request, width, height) } pub fn close(&self, handle: PopupHandle) -> Result<()> { diff --git a/crates/composition/src/system.rs b/crates/composition/src/system.rs index df3eac4..71efe6f 100644 --- a/crates/composition/src/system.rs +++ b/crates/composition/src/system.rs @@ -193,20 +193,12 @@ impl RuntimeState<'_> { req.mode ); - popup_manager.set_pending_popup(req, initial_dimensions.0, initial_dimensions.1); + let popup_handle = + popup_manager.request_popup(req, initial_dimensions.0, initial_dimensions.1); let (instance, popup_key_cell) = Self::create_popup_instance(&definition, &popup_manager, resize_sender)?; - let popup_handle = popup_manager - .current_popup_key() - .map(PopupHandle::new) - .ok_or_else(|| { - Error::Domain(DomainError::Configuration { - message: "No popup key available after creation".to_string(), - }) - })?; - popup_key_cell.set(popup_handle.key()); if let Some(popup_window) = popup_manager.get_popup_window(popup_handle.key()) {