diff --git a/adapters/src/lib.rs b/adapters/src/lib.rs index 1dda49e..d8f4f8c 100644 --- a/adapters/src/lib.rs +++ b/adapters/src/lib.rs @@ -5,7 +5,10 @@ pub mod rendering; pub mod wayland; pub use rendering::femtovg::popup_window::PopupWindow; -pub use rendering::slint_integration::platform::close_current_popup; +pub use rendering::slint_integration::platform::{ + clear_popup_position_override, close_current_popup, get_popup_position_override, + set_popup_position_override, +}; pub mod platform { pub use slint; diff --git a/adapters/src/rendering/slint_integration/platform.rs b/adapters/src/rendering/slint_integration/platform.rs index 756f832..b105573 100644 --- a/adapters/src/rendering/slint_integration/platform.rs +++ b/adapters/src/rendering/slint_integration/platform.rs @@ -24,11 +24,41 @@ pub fn close_current_popup() { }); } +pub fn set_popup_position_override(x: f32, y: f32) { + CURRENT_PLATFORM.with(|platform| { + if let Some(weak_platform) = platform.borrow().as_ref() { + if let Some(strong_platform) = weak_platform.upgrade() { + strong_platform.set_popup_position(x, y); + } + } + }); +} + +#[must_use] +pub fn get_popup_position_override() -> Option<(f32, f32)> { + CURRENT_PLATFORM.with(|platform| { + platform.borrow().as_ref() + .and_then(Weak::upgrade) + .and_then(|strong| strong.get_popup_position()) + }) +} + +pub fn clear_popup_position_override() { + CURRENT_PLATFORM.with(|platform| { + if let Some(weak_platform) = platform.borrow().as_ref() { + if let Some(strong_platform) = weak_platform.upgrade() { + strong_platform.clear_popup_position(); + } + } + }); +} + pub struct CustomSlintPlatform { main_window: Weak, popup_creator: RefCell>>, first_call: Cell, last_popup: RefCell>>, + popup_position: RefCell>, } impl CustomSlintPlatform { @@ -39,6 +69,7 @@ impl CustomSlintPlatform { popup_creator: RefCell::new(None), first_call: Cell::new(true), last_popup: RefCell::new(None), + popup_position: RefCell::new(None), }); CURRENT_PLATFORM.with(|current| { @@ -68,6 +99,19 @@ impl CustomSlintPlatform { } *self.last_popup.borrow_mut() = None; } + + pub fn set_popup_position(&self, x: f32, y: f32) { + *self.popup_position.borrow_mut() = Some((x, y)); + } + + #[must_use] + pub fn get_popup_position(&self) -> Option<(f32, f32)> { + *self.popup_position.borrow() + } + + pub fn clear_popup_position(&self) { + *self.popup_position.borrow_mut() = None; + } } impl Platform for CustomSlintPlatform { diff --git a/adapters/src/wayland/surfaces/popup_manager.rs b/adapters/src/wayland/surfaces/popup_manager.rs index c13b138..ce5c95a 100644 --- a/adapters/src/wayland/surfaces/popup_manager.rs +++ b/adapters/src/wayland/surfaces/popup_manager.rs @@ -1,6 +1,9 @@ use crate::errors::{LayerShikaError, Result}; use crate::rendering::egl::context::EGLContext; use crate::rendering::femtovg::popup_window::PopupWindow; +use crate::rendering::slint_integration::platform::{ + clear_popup_position_override, get_popup_position_override, +}; use log::info; use slab::Slab; use slint::{platform::femtovg_renderer::FemtoVGRenderer, PhysicalSize, WindowSize}; @@ -93,6 +96,15 @@ impl PopupManager { } })?; + let pointer_position = if let Some((x, y)) = get_popup_position_override() { + info!("Using explicit popup position: ({}, {})", x, y); + clear_popup_position_override(); + slint::LogicalPosition::new(x, y) + } else { + log::error!("No popup position provided - using (0, 0) as fallback"); + slint::LogicalPosition::new(0.0, 0.0) + }; + let scale_factor = *self.current_scale_factor.borrow(); let output_size = *self.current_output_size.borrow(); info!( @@ -120,7 +132,7 @@ impl PopupManager { fractional_scale_manager: self.context.fractional_scale_manager.as_ref(), viewporter: self.context.viewporter.as_ref(), queue_handle, - position: slint::LogicalPosition::new(0.0, 0.0), + position: pointer_position, size: popup_size, scale_factor, }); diff --git a/adapters/src/wayland/surfaces/popup_surface.rs b/adapters/src/wayland/surfaces/popup_surface.rs index cead971..35ee444 100644 --- a/adapters/src/wayland/surfaces/popup_surface.rs +++ b/adapters/src/wayland/surfaces/popup_surface.rs @@ -108,23 +108,23 @@ impl PopupSurface { .xdg_wm_base .create_positioner(params.queue_handle, ()); - let x = (params.position.x * params.scale_factor) as i32; - let y = (params.position.y * params.scale_factor) as i32; - let width = params.size.width as i32; - let height = params.size.height as i32; + let x = params.position.x as i32; + let y = params.position.y as i32; + + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] + #[allow(clippy::cast_precision_loss)] + let logical_width = (params.size.width as f32 / params.scale_factor) as i32; + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] + #[allow(clippy::cast_precision_loss)] + let logical_height = (params.size.height as f32 / params.scale_factor) as i32; positioner.set_anchor_rect(x, y, 1, 1); - positioner.set_size(width, height); + positioner.set_size(logical_width, logical_height); positioner.set_anchor(Anchor::TopLeft); positioner.set_gravity(Gravity::BottomRight); - positioner.set_constraint_adjustment( - ConstraintAdjustment::SlideX - | ConstraintAdjustment::SlideY - | ConstraintAdjustment::FlipX - | ConstraintAdjustment::FlipY - | ConstraintAdjustment::ResizeX - | ConstraintAdjustment::ResizeY, - ); + positioner.set_constraint_adjustment(ConstraintAdjustment::None); positioner } diff --git a/composition/src/lib.rs b/composition/src/lib.rs index 063482a..12298f5 100644 --- a/composition/src/lib.rs +++ b/composition/src/lib.rs @@ -11,6 +11,9 @@ pub use builder::LayerShika; pub use layer_shika_adapters::PopupWindow; pub use layer_shika_adapters::close_current_popup; pub use layer_shika_adapters::platform::{calloop, slint, slint_interpreter}; +pub use layer_shika_adapters::{ + clear_popup_position_override, get_popup_position_override, set_popup_position_override, +}; pub use layer_shika_domain::value_objects::anchor::AnchorEdges; pub type Result = StdResult;