refactor: minor popup types

This commit is contained in:
drendog 2025-11-14 23:16:35 +01:00
parent 911f801ece
commit 65a4ff41f7
Signed by: dwenya
GPG key ID: 8DD77074645332D0
5 changed files with 66 additions and 48 deletions

View file

@ -9,7 +9,7 @@ pub use rendering::femtovg::popup_window::PopupWindow;
pub use wayland::config::WaylandWindowConfig; pub use wayland::config::WaylandWindowConfig;
pub use wayland::facade::{PopupManagerFacade, RuntimeStateFacade, WindowingSystemFacade}; pub use wayland::facade::{PopupManagerFacade, RuntimeStateFacade, WindowingSystemFacade};
pub use wayland::shell_adapter::WaylandWindowingSystem; pub use wayland::shell_adapter::WaylandWindowingSystem;
pub use wayland::surfaces::popup_manager::{PopupId, PopupManager}; pub use wayland::surfaces::popup_manager::PopupManager;
pub use wayland::surfaces::surface_state::WindowState; pub use wayland::surfaces::surface_state::WindowState;
pub mod platform { pub mod platform {

View file

@ -1,7 +1,8 @@
use super::renderable_window::{RenderState, RenderableWindow}; use super::renderable_window::{RenderState, RenderableWindow};
use crate::errors::{RenderingError, Result}; use crate::errors::{RenderingError, Result};
use crate::wayland::surfaces::popup_manager::{OnCloseCallback, PopupId}; use crate::wayland::surfaces::popup_manager::OnCloseCallback;
use core::ops::Deref; use core::ops::Deref;
use layer_shika_domain::value_objects::popup_request::PopupHandle;
use log::info; use log::info;
use slint::{ use slint::{
PhysicalSize, Window, WindowSize, PhysicalSize, Window, WindowSize,
@ -17,7 +18,7 @@ pub struct PopupWindow {
render_state: Cell<RenderState>, render_state: Cell<RenderState>,
size: Cell<PhysicalSize>, size: Cell<PhysicalSize>,
scale_factor: Cell<f32>, scale_factor: Cell<f32>,
popup_id: Cell<Option<PopupId>>, popup_handle: Cell<Option<PopupHandle>>,
on_close: OnceCell<OnCloseCallback>, on_close: OnceCell<OnCloseCallback>,
configured: Cell<bool>, configured: Cell<bool>,
component_instance: OnceCell<ComponentInstance>, component_instance: OnceCell<ComponentInstance>,
@ -34,7 +35,7 @@ impl PopupWindow {
render_state: Cell::new(RenderState::Clean), render_state: Cell::new(RenderState::Clean),
size: Cell::new(PhysicalSize::default()), size: Cell::new(PhysicalSize::default()),
scale_factor: Cell::new(1.), scale_factor: Cell::new(1.),
popup_id: Cell::new(None), popup_handle: Cell::new(None),
on_close: OnceCell::new(), on_close: OnceCell::new(),
configured: Cell::new(false), configured: Cell::new(false),
component_instance: OnceCell::new(), component_instance: OnceCell::new(),
@ -49,8 +50,8 @@ impl PopupWindow {
window window
} }
pub fn set_popup_id(&self, id: PopupId) { pub fn set_popup_id(&self, handle: PopupHandle) {
self.popup_id.set(Some(id)); self.popup_handle.set(Some(handle));
} }
pub fn close_popup(&self) { pub fn close_popup(&self) {
@ -60,20 +61,20 @@ impl PopupWindow {
info!("Failed to hide popup window: {e}"); info!("Failed to hide popup window: {e}");
} }
if let Some(id) = self.popup_id.get() { if let Some(handle) = self.popup_handle.get() {
info!("Destroying popup with id {:?}", id); info!("Destroying popup with handle {:?}", handle);
if let Some(on_close) = self.on_close.get() { if let Some(on_close) = self.on_close.get() {
on_close(id); on_close(handle);
} }
} }
self.popup_id.set(None); self.popup_handle.set(None);
info!("Popup window cleanup complete"); info!("Popup window cleanup complete");
} }
pub fn popup_key(&self) -> Option<usize> { pub fn popup_key(&self) -> Option<usize> {
self.popup_id.get().map(PopupId::key) self.popup_handle.get().map(PopupHandle::key)
} }
pub fn mark_configured(&self) { pub fn mark_configured(&self) {

View file

@ -130,8 +130,8 @@ impl EventContext {
ActiveWindow::Main => { ActiveWindow::Main => {
self.main_window.window().dispatch_event(event); self.main_window.window().dispatch_event(event);
} }
ActiveWindow::Popup(index) => { ActiveWindow::Popup(handle) => {
if let Some(popup_window) = popup_manager.get_popup_window(index) { if let Some(popup_window) = popup_manager.get_popup_window(handle.key()) {
popup_window.dispatch_event(event); popup_window.dispatch_event(event);
} }
} }

View file

@ -29,26 +29,31 @@ use super::surface_state::WindowState;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActiveWindow { pub enum ActiveWindow {
Main, Main,
Popup(usize), Popup(PopupHandle),
None, None,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PopupId(pub(crate) usize); struct PopupId(usize);
impl PopupId { impl PopupId {
#[must_use] #[must_use]
pub const fn key(self) -> usize { const fn key(self) -> usize {
self.0 self.0
} }
#[must_use] #[must_use]
pub const fn from_key(key: usize) -> Self { const fn from_handle(handle: PopupHandle) -> Self {
Self(key) Self(handle.key())
}
#[must_use]
const fn to_handle(self) -> PopupHandle {
PopupHandle::new(self.0)
} }
} }
pub type OnCloseCallback = Box<dyn Fn(PopupId)>; pub type OnCloseCallback = Box<dyn Fn(PopupHandle)>;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct CreatePopupParams { pub struct CreatePopupParams {
@ -291,15 +296,16 @@ impl PopupManager {
let on_close: OnCloseCallback = { let on_close: OnCloseCallback = {
let weak_self = Rc::downgrade(self); let weak_self = Rc::downgrade(self);
Box::new(move |id: PopupId| { Box::new(move |handle: PopupHandle| {
if let Some(manager) = weak_self.upgrade() { if let Some(manager) = weak_self.upgrade() {
let id = PopupId::from_handle(handle);
manager.destroy_popup(id); manager.destroy_popup(id);
} }
}) })
}; };
let popup_window = PopupWindow::new_with_callback(renderer, on_close); let popup_window = PopupWindow::new_with_callback(renderer, on_close);
popup_window.set_popup_id(popup_id); popup_window.set_popup_id(popup_id.to_handle());
popup_window.set_scale_factor(scale_factor); popup_window.set_scale_factor(scale_factor);
popup_window.set_size(WindowSize::Logical(slint::LogicalSize::new( popup_window.set_size(WindowSize::Logical(slint::LogicalSize::new(
params.width, params.width,
@ -373,7 +379,7 @@ impl PopupManager {
.map(|popup| Rc::clone(&popup.window)) .map(|popup| Rc::clone(&popup.window))
} }
pub fn destroy_popup(&self, id: PopupId) { fn destroy_popup(&self, id: PopupId) {
if let Some(popup) = self.state.borrow_mut().popups.remove(&id) { if let Some(popup) = self.state.borrow_mut().popups.remove(&id) {
info!("Destroying popup with id {:?}", id); info!("Destroying popup with id {:?}", id);
@ -423,7 +429,7 @@ impl PopupManager {
} }
pub fn close(&self, handle: PopupHandle) -> Result<()> { pub fn close(&self, handle: PopupHandle) -> Result<()> {
let id = PopupId::from_key(handle.key()); let id = PopupId::from_handle(handle);
self.destroy_popup(id); self.destroy_popup(id);
Ok(()) Ok(())
} }
@ -464,8 +470,11 @@ impl PopupManager {
return ActiveWindow::Main; return ActiveWindow::Main;
} }
if let Some(popup_key) = self.find_popup_key_by_surface_id(&surface_id) { if let Some(popup_handle) = self
return ActiveWindow::Popup(popup_key); .find_popup_key_by_surface_id(&surface_id)
.map(PopupHandle::new)
{
return ActiveWindow::Popup(popup_handle);
} }
ActiveWindow::None ActiveWindow::None

View file

@ -8,9 +8,7 @@ use layer_shika_adapters::platform::slint::{ComponentHandle, SharedString};
use layer_shika_adapters::platform::slint_interpreter::{ use layer_shika_adapters::platform::slint_interpreter::{
CompilationResult, ComponentDefinition, ComponentInstance, Value, CompilationResult, ComponentDefinition, ComponentInstance, Value,
}; };
use layer_shika_adapters::{ use layer_shika_adapters::{PopupManager, WaylandWindowConfig, WindowState, WindowingSystemFacade};
PopupId, PopupManager, WaylandWindowConfig, WindowState, WindowingSystemFacade,
};
use layer_shika_domain::config::WindowConfig; use layer_shika_domain::config::WindowConfig;
use layer_shika_domain::errors::DomainError; use layer_shika_domain::errors::DomainError;
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode; use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
@ -27,7 +25,11 @@ use std::time::{Duration, Instant};
pub enum PopupCommand { pub enum PopupCommand {
Show(PopupRequest), Show(PopupRequest),
Close(PopupHandle), Close(PopupHandle),
Resize { key: usize, width: f32, height: f32 }, Resize {
handle: PopupHandle,
width: f32,
height: f32,
},
} }
pub struct EventLoopHandle { pub struct EventLoopHandle {
@ -197,15 +199,18 @@ impl RuntimeState<'_> {
let (instance, popup_key_cell) = let (instance, popup_key_cell) =
Self::create_popup_instance(&definition, &popup_manager, resize_sender)?; Self::create_popup_instance(&definition, &popup_manager, resize_sender)?;
let popup_key = popup_manager.current_popup_key().ok_or_else(|| { let popup_handle = popup_manager
.current_popup_key()
.map(PopupHandle::new)
.ok_or_else(|| {
Error::Domain(DomainError::Configuration { Error::Domain(DomainError::Configuration {
message: "No popup key available after creation".to_string(), message: "No popup key available after creation".to_string(),
}) })
})?; })?;
popup_key_cell.set(popup_key); popup_key_cell.set(popup_handle.key());
if let Some(popup_window) = popup_manager.get_popup_window(popup_key) { if let Some(popup_window) = popup_manager.get_popup_window(popup_handle.key()) {
popup_window.set_component_instance(instance); popup_window.set_component_instance(instance);
} else { } else {
return Err(Error::Domain(DomainError::Configuration { return Err(Error::Domain(DomainError::Configuration {
@ -213,13 +218,12 @@ impl RuntimeState<'_> {
})); }));
} }
Ok(PopupHandle::new(popup_key)) Ok(popup_handle)
} }
pub fn close_popup(&mut self, handle: PopupHandle) -> Result<()> { pub fn close_popup(&mut self, handle: PopupHandle) -> Result<()> {
if let Some(popup_manager) = self.window_state.popup_manager() { if let Some(popup_manager) = self.window_state.popup_manager() {
let id = PopupId::from_key(handle.key()); popup_manager.close(handle)?;
popup_manager.destroy_popup(id);
} }
Ok(()) Ok(())
} }
@ -233,7 +237,7 @@ impl RuntimeState<'_> {
pub fn resize_popup( pub fn resize_popup(
&mut self, &mut self,
key: usize, handle: PopupHandle,
width: f32, width: f32,
height: f32, height: f32,
resize_sender: Option<channel::Sender<PopupCommand>>, resize_sender: Option<channel::Sender<PopupCommand>>,
@ -248,10 +252,10 @@ impl RuntimeState<'_> {
}) })
.cloned()?; .cloned()?;
let Some((request, _serial)) = popup_manager.get_popup_info(key) else { let Some((request, _serial)) = popup_manager.get_popup_info(handle.key()) else {
log::debug!( log::debug!(
"Ignoring resize request for non-existent popup with key {}", "Ignoring resize request for non-existent popup with handle {:?}",
key handle
); );
return Ok(()); return Ok(());
}; };
@ -270,7 +274,7 @@ impl RuntimeState<'_> {
height height
); );
self.close_popup(PopupHandle::new(key))?; self.close_popup(handle)?;
let new_request = PopupRequest::builder(request.component) let new_request = PopupRequest::builder(request.component)
.at(request.at) .at(request.at)
@ -280,7 +284,7 @@ impl RuntimeState<'_> {
self.show_popup(new_request, resize_sender)?; self.show_popup(new_request, resize_sender)?;
} else if size_changed { } else if size_changed {
if let Some(popup_window) = popup_manager.get_popup_window(key) { if let Some(popup_window) = popup_manager.get_popup_window(handle.key()) {
popup_window.request_resize(width, height); popup_window.request_resize(width, height);
} }
} }
@ -337,7 +341,7 @@ impl RuntimeState<'_> {
if sender if sender
.send(PopupCommand::Resize { .send(PopupCommand::Resize {
key: popup_key, handle: PopupHandle::new(popup_key),
width, width,
height, height,
}) })
@ -451,9 +455,13 @@ impl WindowingSystem {
log::error!("Failed to close popup: {}", e); log::error!("Failed to close popup: {}", e);
} }
} }
PopupCommand::Resize { key, width, height } => { PopupCommand::Resize {
handle,
width,
height,
} => {
if let Err(e) = runtime_state.resize_popup( if let Err(e) = runtime_state.resize_popup(
key, handle,
width, width,
height, height,
Some(sender_for_handler.clone()), Some(sender_for_handler.clone()),