diff --git a/crates/composition/src/lib.rs b/crates/composition/src/lib.rs index 71ba8df..f9c516d 100644 --- a/crates/composition/src/lib.rs +++ b/crates/composition/src/lib.rs @@ -1,7 +1,6 @@ #![allow(clippy::pub_use)] mod builder; -mod slint_callbacks; mod system; use layer_shika_adapters::errors::LayerShikaError; @@ -22,8 +21,7 @@ pub use layer_shika_domain::value_objects::popup_positioning_mode::PopupPosition pub use layer_shika_domain::value_objects::popup_request::{ PopupAt, PopupHandle, PopupRequest, PopupSize, }; -pub use slint_callbacks::{SlintCallbackContract, SlintCallbackNames}; -pub use system::{App, EventLoopHandle, ShellContext}; +pub use system::{App, EventLoopHandle, ShellContext, ShellControl}; pub mod calloop { pub use layer_shika_adapters::platform::calloop::{ @@ -50,7 +48,7 @@ pub mod prelude { AnchorEdges, App, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika, OutputGeometry, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry, PopupAt, PopupHandle, PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, - ShellContext, SlintCallbackContract, SlintCallbackNames, + ShellContext, ShellControl, }; pub use crate::calloop::{Generic, Interest, Mode, PostAction, RegistrationToken, Timer}; diff --git a/crates/composition/src/slint_callbacks.rs b/crates/composition/src/slint_callbacks.rs deleted file mode 100644 index 3313951..0000000 --- a/crates/composition/src/slint_callbacks.rs +++ /dev/null @@ -1,277 +0,0 @@ -use crate::system::PopupCommand; -use crate::{Error, Result}; -use layer_shika_adapters::PopupManager; -use layer_shika_adapters::platform::calloop::channel; -use layer_shika_adapters::platform::slint::SharedString; -use layer_shika_adapters::platform::slint_interpreter::{ComponentInstance, Value}; -use layer_shika_domain::errors::DomainError; -use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode; -use layer_shika_domain::value_objects::popup_request::{ - PopupAt, PopupHandle, PopupRequest, PopupSize, -}; -use std::cell::{Cell, RefCell}; -use std::rc::Rc; - -pub struct SlintCallbackNames; - -impl SlintCallbackNames { - pub const SHOW_POPUP: &'static str = "show_popup"; - pub const CHANGE_POPUP_SIZE: &'static str = "change_popup_size"; - pub const SET_POPUP_POSITIONING_MODE: &'static str = "set_popup_positioning_mode"; - pub const POPUP_CLOSED: &'static str = "closed"; -} - -pub struct SlintCallbackContract { - popup_positioning_mode: Rc>, - popup_command_sender: channel::Sender, -} - -impl SlintCallbackContract { - #[must_use] - pub fn new( - popup_positioning_mode: Rc>, - popup_command_sender: channel::Sender, - ) -> Self { - Self { - popup_positioning_mode, - popup_command_sender, - } - } - - pub fn register_on_main_component(&self, component_instance: &ComponentInstance) -> Result<()> { - self.register_set_popup_positioning_mode_callback(component_instance)?; - self.register_show_popup_callback(component_instance)?; - Ok(()) - } - - pub fn register_on_popup_component( - instance: &ComponentInstance, - popup_manager: &Rc, - resize_sender: Option>, - popup_key_cell: &Rc>, - ) -> Result<()> { - Self::register_popup_closed_callback(instance, popup_manager)?; - Self::register_change_popup_size_callback( - instance, - popup_manager, - resize_sender, - popup_key_cell, - ); - Ok(()) - } - - fn register_set_popup_positioning_mode_callback( - &self, - component_instance: &ComponentInstance, - ) -> Result<()> { - let popup_mode_clone = Rc::clone(&self.popup_positioning_mode); - component_instance - .set_callback( - SlintCallbackNames::SET_POPUP_POSITIONING_MODE, - move |args| { - let center_x: bool = args - .first() - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(false); - let center_y: bool = args - .get(1) - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(false); - - let mode = PopupPositioningMode::from_flags(center_x, center_y); - *popup_mode_clone.borrow_mut() = mode; - log::info!( - "Popup positioning mode set to: {:?} (center_x: {}, center_y: {})", - mode, - center_x, - center_y - ); - Value::Void - }, - ) - .map_err(|e| { - Error::Domain(DomainError::Configuration { - message: format!( - "Failed to register {} callback: {}", - SlintCallbackNames::SET_POPUP_POSITIONING_MODE, - e - ), - }) - }) - } - - fn register_show_popup_callback(&self, component_instance: &ComponentInstance) -> Result<()> { - let sender = self.popup_command_sender.clone(); - let popup_mode_for_callback = Rc::clone(&self.popup_positioning_mode); - - component_instance - .set_callback(SlintCallbackNames::SHOW_POPUP, move |args| { - let component_name: SharedString = args - .first() - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or_else(|| SharedString::from("")); - - if component_name.is_empty() { - log::error!( - "{} called without component name", - SlintCallbackNames::SHOW_POPUP - ); - return Value::Void; - } - - let x: f32 = args - .get(1) - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(0.0); - let y: f32 = args - .get(2) - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(0.0); - - let mode = *popup_mode_for_callback.borrow(); - - let request = PopupRequest::builder(component_name.to_string()) - .at(PopupAt::absolute(x, y)) - .size(PopupSize::content()) - .mode(mode) - .build(); - - if sender.send(PopupCommand::Show(request)).is_err() { - log::error!("Failed to send popup show command through channel"); - } - Value::Void - }) - .map_err(|e| { - Error::Domain(DomainError::Configuration { - message: format!( - "Failed to register {} callback: {}", - SlintCallbackNames::SHOW_POPUP, - e - ), - }) - }) - } - - fn register_popup_closed_callback( - instance: &ComponentInstance, - popup_manager: &Rc, - ) -> Result<()> { - let popup_manager_weak = Rc::downgrade(popup_manager); - instance - .set_callback(SlintCallbackNames::POPUP_CLOSED, move |_| { - if let Some(popup_manager) = popup_manager_weak.upgrade() { - popup_manager.close_current_popup(); - } - Value::Void - }) - .map_err(|e| { - Error::Domain(DomainError::Configuration { - message: format!( - "Failed to set {} callback: {}", - SlintCallbackNames::POPUP_CLOSED, - e - ), - }) - }) - } - - fn register_change_popup_size_callback( - instance: &ComponentInstance, - popup_manager: &Rc, - resize_sender: Option>, - popup_key_cell: &Rc>, - ) { - let result = if let Some(sender) = resize_sender { - let key_cell = Rc::clone(popup_key_cell); - instance.set_callback(SlintCallbackNames::CHANGE_POPUP_SIZE, move |args| { - let width: f32 = args - .first() - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(200.0); - let height: f32 = args - .get(1) - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(150.0); - - let popup_key = key_cell.get(); - log::info!( - "{} callback invoked: {}x{} for key {}", - SlintCallbackNames::CHANGE_POPUP_SIZE, - width, - height, - popup_key - ); - - if sender - .send(PopupCommand::Resize { - handle: PopupHandle::new(popup_key), - width, - height, - }) - .is_err() - { - log::error!("Failed to send popup resize command through channel"); - } - Value::Void - }) - } else { - let popup_manager_for_resize = Rc::downgrade(popup_manager); - let key_cell = Rc::clone(popup_key_cell); - instance.set_callback(SlintCallbackNames::CHANGE_POPUP_SIZE, move |args| { - let width: f32 = args - .first() - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(200.0); - let height: f32 = args - .get(1) - .and_then(|v| v.clone().try_into().ok()) - .unwrap_or(150.0); - - let popup_key = key_cell.get(); - log::info!( - "{} callback invoked: {}x{} for key {}", - SlintCallbackNames::CHANGE_POPUP_SIZE, - width, - height, - popup_key - ); - - if let Some(popup_manager) = popup_manager_for_resize.upgrade() { - if let Some(popup_window) = popup_manager.get_popup_window(popup_key) { - popup_window.request_resize(width, height); - - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_possible_wrap)] - let logical_width = width as i32; - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_possible_wrap)] - let logical_height = height as i32; - - popup_manager.update_popup_viewport(popup_key, logical_width, logical_height); - log::debug!( - "Updated popup viewport to logical size: {}x{} (from direct resize to {}x{})", - logical_width, - logical_height, - width, - height - ); - } - } - Value::Void - }) - }; - - if let Err(e) = result { - log::warn!( - "Failed to set {} callback: {}", - SlintCallbackNames::CHANGE_POPUP_SIZE, - e - ); - } else { - log::info!( - "{} callback registered successfully", - SlintCallbackNames::CHANGE_POPUP_SIZE - ); - } - } -} diff --git a/crates/composition/src/system.rs b/crates/composition/src/system.rs index cca2934..cfbc260 100644 --- a/crates/composition/src/system.rs +++ b/crates/composition/src/system.rs @@ -1,4 +1,3 @@ -use crate::slint_callbacks::SlintCallbackContract; use crate::{Error, Result}; use layer_shika_adapters::errors::EventLoopError; use layer_shika_adapters::platform::calloop::{ @@ -7,7 +6,7 @@ use layer_shika_adapters::platform::calloop::{ }; use layer_shika_adapters::platform::slint::ComponentHandle; use layer_shika_adapters::platform::slint_interpreter::{ - CompilationResult, ComponentDefinition, ComponentInstance, + CompilationResult, ComponentDefinition, ComponentInstance, Value, }; use layer_shika_adapters::{ AppState, PopupManager, WaylandWindowConfig, WindowState, WindowingSystemFacade, @@ -17,7 +16,7 @@ use layer_shika_domain::entities::output_registry::OutputRegistry; use layer_shika_domain::errors::DomainError; use layer_shika_domain::value_objects::output_handle::OutputHandle; use layer_shika_domain::value_objects::output_info::OutputInfo; -use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode; +use layer_shika_domain::value_objects::dimensions::PopupDimensions; use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest, PopupSize}; use std::cell::Cell; use std::cell::RefCell; @@ -36,6 +35,47 @@ pub enum PopupCommand { }, } +#[derive(Clone)] +pub struct ShellControl { + sender: channel::Sender, +} + +impl ShellControl { + pub fn show_popup(&self, request: &PopupRequest) -> Result<()> { + self.sender + .send(PopupCommand::Show(request.clone())) + .map_err(|_| { + Error::Domain(DomainError::Configuration { + message: "Failed to send popup show command: channel closed".to_string(), + }) + }) + } + + pub fn close_popup(&self, handle: PopupHandle) -> Result<()> { + self.sender + .send(PopupCommand::Close(handle)) + .map_err(|_| { + Error::Domain(DomainError::Configuration { + message: "Failed to send popup close command: channel closed".to_string(), + }) + }) + } + + pub fn resize_popup(&self, handle: PopupHandle, width: f32, height: f32) -> Result<()> { + self.sender + .send(PopupCommand::Resize { + handle, + width, + height, + }) + .map_err(|_| { + Error::Domain(DomainError::Configuration { + message: "Failed to send popup resize command: channel closed".to_string(), + }) + }) + } +} + pub struct EventLoopHandle { system: Weak>, } @@ -128,6 +168,18 @@ pub struct ShellContext<'a> { app_state: &'a mut AppState, } +fn extract_dimensions_from_callback(args: &[Value]) -> PopupDimensions { + let defaults = PopupDimensions::default(); + PopupDimensions::new( + args.first() + .and_then(|v| v.clone().try_into().ok()) + .unwrap_or(defaults.width), + args.get(1) + .and_then(|v| v.clone().try_into().ok()) + .unwrap_or(defaults.height), + ) +} + impl ShellContext<'_> { #[must_use] pub fn component_instance(&self) -> Option<&ComponentInstance> { @@ -204,8 +256,8 @@ impl ShellContext<'_> { pub fn show_popup( &mut self, - req: PopupRequest, - resize_sender: Option>, + req: &PopupRequest, + resize_control: Option, ) -> Result { let compilation_result = self.compilation_result().ok_or_else(|| { Error::Domain(DomainError::Configuration { @@ -266,10 +318,10 @@ impl ShellContext<'_> { ); let popup_handle = - popup_manager.request_popup(req, initial_dimensions.0, initial_dimensions.1); + popup_manager.request_popup(req.clone(), initial_dimensions.0, initial_dimensions.1); let (instance, popup_key_cell) = - Self::create_popup_instance(&definition, &popup_manager, resize_sender)?; + Self::create_popup_instance(&definition, &popup_manager, resize_control, req)?; popup_key_cell.set(popup_handle.key()); @@ -307,7 +359,7 @@ impl ShellContext<'_> { handle: PopupHandle, width: f32, height: f32, - resize_sender: Option>, + resize_control: Option, ) -> Result<()> { let active_window = self.active_or_primary_output().ok_or_else(|| { Error::Domain(DomainError::Configuration { @@ -345,13 +397,21 @@ impl ShellContext<'_> { self.close_popup(handle)?; - let new_request = PopupRequest::builder(request.component) + let mut builder = PopupRequest::builder(request.component) .at(request.at) .size(PopupSize::fixed(width, height)) - .mode(request.mode) - .build(); + .mode(request.mode); - self.show_popup(new_request, resize_sender)?; + if let Some(close_cb) = &request.close_callback { + builder = builder.close_on(close_cb.clone()); + } + if let Some(resize_cb) = &request.resize_callback { + builder = builder.resize_on(resize_cb.clone()); + } + + let new_request = builder.build(); + + self.show_popup(&new_request, resize_control)?; } else if size_changed { if let Some(popup_window) = popup_manager.get_popup_window(handle.key()) { popup_window.request_resize(width, height); @@ -380,7 +440,8 @@ impl ShellContext<'_> { fn create_popup_instance( definition: &ComponentDefinition, popup_manager: &Rc, - resize_sender: Option>, + resize_control: Option, + req: &PopupRequest, ) -> Result<(ComponentInstance, Rc>)> { let instance = definition.create().map_err(|e| { Error::Domain(DomainError::Configuration { @@ -390,11 +451,12 @@ impl ShellContext<'_> { let popup_key_cell = Rc::new(Cell::new(0)); - SlintCallbackContract::register_on_popup_component( + Self::register_popup_callbacks( &instance, popup_manager, - resize_sender, + resize_control, &popup_key_cell, + req, )?; instance.show().map_err(|e| { @@ -405,12 +467,158 @@ impl ShellContext<'_> { Ok((instance, popup_key_cell)) } + + fn register_popup_callbacks( + instance: &ComponentInstance, + popup_manager: &Rc, + resize_control: Option, + popup_key_cell: &Rc>, + req: &PopupRequest, + ) -> Result<()> { + if let Some(close_callback_name) = &req.close_callback { + Self::register_close_callback(instance, popup_manager, close_callback_name)?; + } + + if let Some(resize_callback_name) = &req.resize_callback { + Self::register_resize_callback( + instance, + popup_manager, + resize_control, + popup_key_cell, + resize_callback_name, + )?; + } + + Ok(()) + } + + fn register_close_callback( + instance: &ComponentInstance, + popup_manager: &Rc, + callback_name: &str, + ) -> Result<()> { + let popup_manager_weak = Rc::downgrade(popup_manager); + instance + .set_callback(callback_name, move |_| { + if let Some(popup_manager) = popup_manager_weak.upgrade() { + popup_manager.close_current_popup(); + } + Value::Void + }) + .map_err(|e| { + Error::Domain(DomainError::Configuration { + message: format!("Failed to set '{}' callback: {}", callback_name, e), + }) + }) + } + + fn register_resize_callback( + instance: &ComponentInstance, + popup_manager: &Rc, + resize_control: Option, + popup_key_cell: &Rc>, + callback_name: &str, + ) -> Result<()> { + if let Some(control) = resize_control { + Self::register_resize_with_control(instance, popup_key_cell, &control, callback_name) + } else { + Self::register_resize_direct(instance, popup_manager, popup_key_cell, callback_name) + } + } + + fn register_resize_with_control( + instance: &ComponentInstance, + popup_key_cell: &Rc>, + control: &ShellControl, + callback_name: &str, + ) -> Result<()> { + let key_cell = Rc::clone(popup_key_cell); + let control = control.clone(); + instance + .set_callback(callback_name, move |args| { + let dimensions = extract_dimensions_from_callback(args); + let popup_key = key_cell.get(); + + log::info!( + "Resize callback invoked: {}x{} for key {}", + dimensions.width, + dimensions.height, + popup_key + ); + + if control + .resize_popup(PopupHandle::new(popup_key), dimensions.width, dimensions.height) + .is_err() + { + log::error!("Failed to resize popup through control"); + } + Value::Void + }) + .map_err(|e| { + Error::Domain(DomainError::Configuration { + message: format!("Failed to set '{}' callback: {}", callback_name, e), + }) + }) + } + + fn register_resize_direct( + instance: &ComponentInstance, + popup_manager: &Rc, + popup_key_cell: &Rc>, + callback_name: &str, + ) -> Result<()> { + let popup_manager_weak = Rc::downgrade(popup_manager); + let key_cell = Rc::clone(popup_key_cell); + instance + .set_callback(callback_name, move |args| { + let dimensions = extract_dimensions_from_callback(args); + let popup_key = key_cell.get(); + + log::info!( + "Resize callback invoked: {}x{} for key {}", + dimensions.width, + dimensions.height, + popup_key + ); + + if let Some(popup_manager) = popup_manager_weak.upgrade() { + if let Some(popup_window) = popup_manager.get_popup_window(popup_key) { + popup_window.request_resize(dimensions.width, dimensions.height); + + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_possible_wrap)] + let logical_width = dimensions.width as i32; + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_possible_wrap)] + let logical_height = dimensions.height as i32; + + popup_manager.update_popup_viewport( + popup_key, + logical_width, + logical_height, + ); + log::debug!( + "Updated popup viewport to logical size: {}x{} (from direct resize to {}x{})", + logical_width, + logical_height, + dimensions.width, + dimensions.height + ); + } + } + Value::Void + }) + .map_err(|e| { + Error::Domain(DomainError::Configuration { + message: format!("Failed to set '{}' callback: {}", callback_name, e), + }) + }) + } } pub struct App { inner: Rc>, popup_command_sender: channel::Sender, - callback_contract: SlintCallbackContract, } impl App { @@ -430,25 +638,19 @@ impl App { let (sender, receiver) = channel::channel(); - let popup_positioning_mode = Rc::new(RefCell::new(PopupPositioningMode::Center)); - let callback_contract = - SlintCallbackContract::new(Rc::clone(&popup_positioning_mode), sender.clone()); - let system = Self { inner: Rc::clone(&inner_rc), popup_command_sender: sender, - callback_contract, }; system.setup_popup_command_handler(receiver)?; - system.register_popup_callbacks(); Ok(system) } fn setup_popup_command_handler(&self, receiver: channel::Channel) -> Result<()> { let loop_handle = self.inner.borrow().inner_ref().event_loop_handle(); - let sender_for_handler = self.popup_command_sender.clone(); + let control = self.control(); loop_handle .insert_source(receiver, move |event, (), app_state| { @@ -457,8 +659,7 @@ impl App { match command { PopupCommand::Show(request) => { - if let Err(e) = - shell_context.show_popup(request, Some(sender_for_handler.clone())) + if let Err(e) = shell_context.show_popup(&request, Some(control.clone())) { log::error!("Failed to show popup: {}", e); } @@ -473,12 +674,9 @@ impl App { width, height, } => { - if let Err(e) = shell_context.resize_popup( - handle, - width, - height, - Some(sender_for_handler.clone()), - ) { + if let Err(e) = + shell_context.resize_popup(handle, width, height, Some(control.clone())) + { log::error!("Failed to resize popup: {}", e); } } @@ -497,15 +695,11 @@ impl App { Ok(()) } - fn register_popup_callbacks(&self) { - self.with_all_component_instances(|component_instance| { - if let Err(e) = self - .callback_contract - .register_on_main_component(component_instance) - { - log::error!("Failed to register popup callbacks on output: {}", e); - } - }); + #[must_use] + pub fn control(&self) -> ShellControl { + ShellControl { + sender: self.popup_command_sender.clone(), + } } #[must_use] @@ -515,24 +709,55 @@ impl App { } } - pub fn request_show_popup(&self, request: PopupRequest) -> Result<()> { - self.popup_command_sender - .send(PopupCommand::Show(request)) - .map_err(|_| { - Error::Domain(DomainError::Configuration { - message: "Failed to send popup show command: channel closed".to_string(), - }) - }) + pub fn on_callback(&self, callback_name: &str, handler: F) -> Result<()> + where + F: Fn(&[Value], ShellControl) -> Value + 'static, + { + let control = self.control(); + let handler = Rc::new(handler); + self.with_all_component_instances(|instance| { + let handler_rc = Rc::clone(&handler); + let control_clone = control.clone(); + if let Err(e) = instance.set_callback(callback_name, move |args| { + handler_rc(args, control_clone.clone()) + }) { + log::error!( + "Failed to register callback '{}' on component: {}", + callback_name, + e + ); + } + }); + Ok(()) } - pub fn request_close_popup(&self, handle: PopupHandle) -> Result<()> { - self.popup_command_sender - .send(PopupCommand::Close(handle)) - .map_err(|_| { - Error::Domain(DomainError::Configuration { - message: "Failed to send popup close command: channel closed".to_string(), - }) - }) + pub fn bind_popup(&self, callback_name: &str, config_builder: F) -> Result<()> + where + F: Fn() -> PopupRequest + 'static, + { + let control = self.control(); + let builder = Rc::new(config_builder); + + self.with_all_component_instances(|instance| { + let builder_clone = Rc::clone(&builder); + let control_clone = control.clone(); + + if let Err(e) = instance.set_callback(callback_name, move |_args| { + let request = builder_clone(); + if let Err(e) = control_clone.show_popup(&request) { + log::error!("Failed to show popup: {}", e); + } + Value::Void + }) { + log::error!( + "Failed to bind popup callback '{}': {}", + callback_name, + e + ); + } + }); + + Ok(()) } pub fn run(&mut self) -> Result<()> { diff --git a/crates/domain/src/prelude.rs b/crates/domain/src/prelude.rs index 384fdb7..5406be3 100644 --- a/crates/domain/src/prelude.rs +++ b/crates/domain/src/prelude.rs @@ -11,7 +11,7 @@ pub use crate::entities::window::WindowHandle; pub use crate::errors::{DomainError, Result}; pub use crate::surface_dimensions::SurfaceDimensions; pub use crate::value_objects::anchor::AnchorEdges; -pub use crate::value_objects::dimensions::WindowHeight; +pub use crate::value_objects::dimensions::{PopupDimensions, WindowHeight}; pub use crate::value_objects::keyboard_interactivity::KeyboardInteractivity; pub use crate::value_objects::layer::Layer; pub use crate::value_objects::margins::Margins; diff --git a/crates/domain/src/value_objects/dimensions.rs b/crates/domain/src/value_objects/dimensions.rs index ec881f5..aeafd90 100644 --- a/crates/domain/src/value_objects/dimensions.rs +++ b/crates/domain/src/value_objects/dimensions.rs @@ -31,3 +31,35 @@ impl From for WindowHeight { Self::new(height) } } + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct PopupDimensions { + pub width: f32, + pub height: f32, +} + +impl Default for PopupDimensions { + fn default() -> Self { + Self { + width: 200.0, + height: 150.0, + } + } +} + +impl PopupDimensions { + #[must_use] + pub const fn new(width: f32, height: f32) -> Self { + Self { width, height } + } + + #[must_use] + pub const fn width(&self) -> f32 { + self.width + } + + #[must_use] + pub const fn height(&self) -> f32 { + self.height + } +} diff --git a/crates/domain/src/value_objects/popup_request.rs b/crates/domain/src/value_objects/popup_request.rs index 9aa2315..6ddbd65 100644 --- a/crates/domain/src/value_objects/popup_request.rs +++ b/crates/domain/src/value_objects/popup_request.rs @@ -22,6 +22,8 @@ pub struct PopupRequest { pub size: PopupSize, pub mode: PopupPositioningMode, pub grab: bool, + pub close_callback: Option, + pub resize_callback: Option, } impl PopupRequest { @@ -38,6 +40,8 @@ impl PopupRequest { size, mode, grab: false, + close_callback: None, + resize_callback: None, } } @@ -111,6 +115,8 @@ pub struct PopupRequestBuilder { size: PopupSize, mode: PopupPositioningMode, grab: bool, + close_callback: Option, + resize_callback: Option, } impl PopupRequestBuilder { @@ -122,6 +128,8 @@ impl PopupRequestBuilder { size: PopupSize::Content, mode: PopupPositioningMode::default(), grab: false, + close_callback: None, + resize_callback: None, } } @@ -149,6 +157,18 @@ impl PopupRequestBuilder { self } + #[must_use] + pub fn close_on(mut self, callback_name: impl Into) -> Self { + self.close_callback = Some(callback_name.into()); + self + } + + #[must_use] + pub fn resize_on(mut self, callback_name: impl Into) -> Self { + self.resize_callback = Some(callback_name.into()); + self + } + #[must_use] pub fn build(self) -> PopupRequest { PopupRequest { @@ -157,6 +177,8 @@ impl PopupRequestBuilder { size: self.size, mode: self.mode, grab: self.grab, + close_callback: self.close_callback, + resize_callback: self.resize_callback, } } } diff --git a/src/lib.rs b/src/lib.rs index 2b8b26a..2a85205 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,8 +44,7 @@ pub mod prelude; pub use layer_shika_composition::{ AnchorEdges, App, Error, EventLoopHandle, KeyboardInteractivity, Layer, LayerShika, OutputGeometry, OutputHandle, OutputInfo, OutputPolicy, OutputRegistry, PopupAt, PopupHandle, - PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, ShellContext, - SlintCallbackContract, SlintCallbackNames, + PopupPositioningMode, PopupRequest, PopupSize, PopupWindow, Result, ShellContext, ShellControl, }; pub use layer_shika_composition::{slint, slint_interpreter}; diff --git a/src/prelude.rs b/src/prelude.rs index 1eaca8b..5dc4406 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,8 +10,7 @@ // Core API types pub use crate::{ - App, Error, EventLoopHandle, LayerShika, PopupWindow, Result, ShellContext, - SlintCallbackContract, SlintCallbackNames, + App, Error, EventLoopHandle, LayerShika, PopupWindow, Result, ShellContext, ShellControl, }; // Domain value objects