refactor: interior mutuability refactor

This commit is contained in:
drendog 2025-11-10 23:01:58 +01:00
parent 4022ca1484
commit d2930a7a85
Signed by: dwenya
GPG key ID: 8DD77074645332D0
10 changed files with 126 additions and 124 deletions

View file

@ -7,7 +7,7 @@ use slint::{
platform::{Renderer, WindowAdapter, WindowEvent, femtovg_renderer::FemtoVGRenderer}, platform::{Renderer, WindowAdapter, WindowEvent, femtovg_renderer::FemtoVGRenderer},
}; };
use slint_interpreter::ComponentInstance; use slint_interpreter::ComponentInstance;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, OnceCell, RefCell};
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use super::main_window::RenderState; use super::main_window::RenderState;
@ -22,7 +22,7 @@ pub struct PopupWindow {
popup_manager: RefCell<Weak<PopupManager>>, popup_manager: RefCell<Weak<PopupManager>>,
popup_key: Cell<Option<usize>>, popup_key: Cell<Option<usize>>,
configured: Cell<bool>, configured: Cell<bool>,
component_instance: RefCell<Option<ComponentInstance>>, component_instance: OnceCell<ComponentInstance>,
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -40,7 +40,7 @@ impl PopupWindow {
popup_manager: RefCell::new(Weak::new()), popup_manager: RefCell::new(Weak::new()),
popup_key: Cell::new(None), popup_key: Cell::new(None),
configured: Cell::new(false), configured: Cell::new(false),
component_instance: RefCell::new(None), component_instance: OnceCell::new(),
} }
}) })
} }
@ -121,7 +121,9 @@ impl PopupWindow {
pub fn set_component_instance(&self, instance: ComponentInstance) { pub fn set_component_instance(&self, instance: ComponentInstance) {
info!("Setting component instance for popup window"); info!("Setting component instance for popup window");
*self.component_instance.borrow_mut() = Some(instance); if self.component_instance.set(instance).is_err() {
info!("Component instance already set for popup window");
}
} }
pub fn request_resize(&self, width: f32, height: f32) { pub fn request_resize(&self, width: f32, height: f32) {

View file

@ -2,7 +2,7 @@ use slint::{
PlatformError, PlatformError,
platform::{Platform, WindowAdapter}, platform::{Platform, WindowAdapter},
}; };
use std::cell::{Cell, RefCell}; use std::cell::{Cell, OnceCell};
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use crate::rendering::femtovg::main_window::FemtoVGWindow; use crate::rendering::femtovg::main_window::FemtoVGWindow;
@ -11,7 +11,7 @@ type PopupCreator = dyn Fn() -> Result<Rc<dyn WindowAdapter>, PlatformError>;
pub struct CustomSlintPlatform { pub struct CustomSlintPlatform {
main_window: Weak<FemtoVGWindow>, main_window: Weak<FemtoVGWindow>,
popup_creator: RefCell<Option<Rc<PopupCreator>>>, popup_creator: OnceCell<Rc<PopupCreator>>,
first_call: Cell<bool>, first_call: Cell<bool>,
} }
@ -20,7 +20,7 @@ impl CustomSlintPlatform {
pub fn new(window: &Rc<FemtoVGWindow>) -> Rc<Self> { pub fn new(window: &Rc<FemtoVGWindow>) -> Rc<Self> {
Rc::new(Self { Rc::new(Self {
main_window: Rc::downgrade(window), main_window: Rc::downgrade(window),
popup_creator: RefCell::new(None), popup_creator: OnceCell::new(),
first_call: Cell::new(true), first_call: Cell::new(true),
}) })
} }
@ -29,7 +29,9 @@ impl CustomSlintPlatform {
where where
F: Fn() -> Result<Rc<dyn WindowAdapter>, PlatformError> + 'static, F: Fn() -> Result<Rc<dyn WindowAdapter>, PlatformError> + 'static,
{ {
*self.popup_creator.borrow_mut() = Some(Rc::new(creator)); if self.popup_creator.set(Rc::new(creator)).is_err() {
log::warn!("Popup creator already set, ignoring new creator");
}
} }
} }
@ -41,7 +43,7 @@ impl Platform for CustomSlintPlatform {
.upgrade() .upgrade()
.ok_or(PlatformError::NoPlatform) .ok_or(PlatformError::NoPlatform)
.map(|w| w as Rc<dyn WindowAdapter>) .map(|w| w as Rc<dyn WindowAdapter>)
} else if let Some(creator) = self.popup_creator.borrow().as_ref() { } else if let Some(creator) = self.popup_creator.get() {
creator() creator()
} else { } else {
Err(PlatformError::NoPlatform) Err(PlatformError::NoPlatform)

View file

@ -170,7 +170,7 @@ impl Dispatch<WlPointer, ()> for WindowState {
state.set_last_pointer_serial(serial); state.set_last_pointer_serial(serial);
state.set_current_pointer_position(surface_x, surface_y); state.set_current_pointer_position(surface_x, surface_y);
state.find_window_for_surface(&surface); state.set_entered_surface(&surface);
let position = state.current_pointer_position(); let position = state.current_pointer_position();
state.dispatch_to_active_window(WindowEvent::PointerMoved { position }); state.dispatch_to_active_window(WindowEvent::PointerMoved { position });
@ -189,7 +189,7 @@ impl Dispatch<WlPointer, ()> for WindowState {
wl_pointer::Event::Leave { .. } => { wl_pointer::Event::Leave { .. } => {
state.dispatch_to_active_window(WindowEvent::PointerExited); state.dispatch_to_active_window(WindowEvent::PointerExited);
state.clear_active_window(); state.clear_entered_surface();
} }
wl_pointer::Event::Button { wl_pointer::Event::Button {
@ -290,7 +290,6 @@ impl Dispatch<XdgPopup, ()> for WindowState {
if let Some(handle) = popup_handle { if let Some(handle) = popup_handle {
info!("Destroying popup with handle {handle:?}"); info!("Destroying popup with handle {handle:?}");
state.clear_active_window_if_popup(handle.key());
if let Some(popup_service) = state.popup_service() { if let Some(popup_service) = state.popup_service() {
let _result = popup_service.close(handle); let _result = popup_service.close(handle);
} }

View file

@ -3,9 +3,9 @@ use crate::rendering::femtovg::popup_window::PopupWindow;
use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest}; use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest};
use log::info; use log::info;
use slint::PhysicalSize; use slint::PhysicalSize;
use std::cell::{Cell, RefCell}; use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
use wayland_client::{backend::ObjectId, protocol::wl_surface::WlSurface, Proxy}; use wayland_client::{Proxy, backend::ObjectId, protocol::wl_surface::WlSurface};
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1; use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
use super::super::surfaces::popup_manager::PopupManager; use super::super::surfaces::popup_manager::PopupManager;
@ -14,11 +14,11 @@ use super::super::surfaces::popup_manager::PopupManager;
pub enum ActiveWindow { pub enum ActiveWindow {
Main, Main,
Popup(usize), Popup(usize),
None,
} }
pub struct PopupService { pub struct PopupService {
manager: Rc<PopupManager>, manager: Rc<PopupManager>,
active_window: RefCell<Option<ActiveWindow>>,
scale_factor: Cell<f32>, scale_factor: Cell<f32>,
} }
@ -28,7 +28,6 @@ impl PopupService {
let scale_factor = manager.scale_factor(); let scale_factor = manager.scale_factor();
Self { Self {
manager, manager,
active_window: RefCell::new(None),
scale_factor: Cell::new(scale_factor), scale_factor: Cell::new(scale_factor),
} }
} }
@ -38,16 +37,11 @@ impl PopupService {
} }
pub fn close(&self, handle: PopupHandle) -> Result<()> { pub fn close(&self, handle: PopupHandle) -> Result<()> {
let key = handle.key(); self.manager.destroy_popup(handle.key());
self.clear_active_window_if_popup(key);
self.manager.destroy_popup(key);
Ok(()) Ok(())
} }
pub fn close_current(&self) { pub fn close_current(&self) {
if let Some(key) = self.manager.current_popup_key() {
self.clear_active_window_if_popup(key);
}
self.manager.close_current_popup(); self.manager.close_current_popup();
} }
@ -99,35 +93,23 @@ impl PopupService {
self.scale_factor.get() self.scale_factor.get()
} }
pub fn find_window_for_surface(&self, surface: &WlSurface, main_surface_id: &ObjectId) { #[must_use]
pub fn get_active_window(
&self,
surface: &WlSurface,
main_surface_id: &ObjectId,
) -> ActiveWindow {
let surface_id = surface.id(); let surface_id = surface.id();
if *main_surface_id == surface_id { if *main_surface_id == surface_id {
*self.active_window.borrow_mut() = Some(ActiveWindow::Main); return ActiveWindow::Main;
return;
} }
if let Some(popup_key) = self.manager.find_popup_key_by_surface_id(&surface_id) { if let Some(popup_key) = self.manager.find_popup_key_by_surface_id(&surface_id) {
*self.active_window.borrow_mut() = Some(ActiveWindow::Popup(popup_key)); return ActiveWindow::Popup(popup_key);
return;
} }
*self.active_window.borrow_mut() = None; ActiveWindow::None
}
#[must_use]
pub fn active_window(&self) -> Option<ActiveWindow> {
*self.active_window.borrow()
}
pub fn clear_active_window(&self) {
*self.active_window.borrow_mut() = None;
}
pub fn clear_active_window_if_popup(&self, popup_key: usize) {
if *self.active_window.borrow() == Some(ActiveWindow::Popup(popup_key)) {
*self.active_window.borrow_mut() = None;
}
} }
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
@ -138,8 +120,8 @@ impl PopupService {
) { ) {
let fractional_scale_id = fractional_scale_proxy.id(); let fractional_scale_id = fractional_scale_proxy.id();
if let Some(popup_key) = if let Some(popup_key) = self
self.manager .manager
.find_popup_key_by_fractional_scale_id(&fractional_scale_id) .find_popup_key_by_fractional_scale_id(&fractional_scale_id)
{ {
if let Some(popup_window) = self.manager.get_popup_window(popup_key) { if let Some(popup_window) = self.manager.get_popup_window(popup_key) {

View file

@ -25,26 +25,20 @@ impl EventRouter {
self.popup_service = Some(popup_service); self.popup_service = Some(popup_service);
} }
pub fn find_window_for_surface(&mut self, surface: &WlSurface) { pub fn dispatch_to_active_window(&self, event: WindowEvent, surface: &WlSurface) {
if let Some(popup_service) = &self.popup_service { if let Some(popup_service) = &self.popup_service {
popup_service.find_window_for_surface(surface, &self.main_surface_id); match popup_service.get_active_window(surface, &self.main_surface_id) {
} ActiveWindow::Main => {
}
pub fn dispatch_to_active_window(&self, event: WindowEvent) {
if let Some(popup_service) = &self.popup_service {
match popup_service.active_window() {
Some(ActiveWindow::Main) => {
self.main_window.window().dispatch_event(event); self.main_window.window().dispatch_event(event);
} }
Some(ActiveWindow::Popup(index)) => { ActiveWindow::Popup(index) => {
if let Some(popup_window) = if let Some(popup_window) =
popup_service.get_popup_window(PopupHandle::new(index)) popup_service.get_popup_window(PopupHandle::new(index))
{ {
popup_window.dispatch_event(event); popup_window.dispatch_event(event);
} }
} }
None => {} ActiveWindow::None => {}
} }
} }
} }

View file

@ -55,12 +55,8 @@ impl InteractionState {
self.event_router.set_popup_service(popup_service); self.event_router.set_popup_service(popup_service);
} }
pub fn find_window_for_surface(&mut self, surface: &WlSurface) { pub fn dispatch_to_active_window(&self, event: WindowEvent, surface: &WlSurface) {
self.event_router.find_window_for_surface(surface); self.event_router.dispatch_to_active_window(event, surface);
}
pub fn dispatch_to_active_window(&self, event: WindowEvent) {
self.event_router.dispatch_to_active_window(event);
} }
pub fn scale_factor(&self) -> f32 { pub fn scale_factor(&self) -> f32 {

View file

@ -76,23 +76,35 @@ impl Drop for ActivePopup {
} }
} }
struct PopupState {
scale_factor: f32,
output_size: PhysicalSize,
}
struct PendingPopup { struct PendingPopup {
request: PopupRequest, request: PopupRequest,
width: f32, width: f32,
height: f32, height: f32,
} }
struct PopupManagerState {
popups: Slab<ActivePopup>,
scale_factor: f32,
output_size: PhysicalSize,
current_popup_key: Option<usize>,
pending_popup: Option<PendingPopup>,
}
impl PopupManagerState {
fn new(initial_scale_factor: f32) -> Self {
Self {
popups: Slab::new(),
scale_factor: initial_scale_factor,
output_size: PhysicalSize::new(0, 0),
current_popup_key: None,
pending_popup: None,
}
}
}
pub struct PopupManager { pub struct PopupManager {
context: PopupContext, context: PopupContext,
popups: RefCell<Slab<ActivePopup>>, state: RefCell<PopupManagerState>,
state: RefCell<PopupState>,
current_popup_key: RefCell<Option<usize>>,
pending_popup: RefCell<Option<PendingPopup>>,
} }
impl PopupManager { impl PopupManager {
@ -100,18 +112,12 @@ impl PopupManager {
pub fn new(context: PopupContext, initial_scale_factor: f32) -> Self { pub fn new(context: PopupContext, initial_scale_factor: f32) -> Self {
Self { Self {
context, context,
popups: RefCell::new(Slab::new()), state: RefCell::new(PopupManagerState::new(initial_scale_factor)),
state: RefCell::new(PopupState {
scale_factor: initial_scale_factor,
output_size: PhysicalSize::new(0, 0),
}),
current_popup_key: RefCell::new(None),
pending_popup: RefCell::new(None),
} }
} }
pub fn set_pending_popup(&self, request: PopupRequest, width: f32, height: f32) { pub fn set_pending_popup(&self, request: PopupRequest, width: f32, height: f32) {
*self.pending_popup.borrow_mut() = Some(PendingPopup { self.state.borrow_mut().pending_popup = Some(PendingPopup {
request, request,
width, width,
height, height,
@ -120,8 +126,9 @@ impl PopupManager {
#[must_use] #[must_use]
pub fn take_pending_popup(&self) -> Option<(PopupRequest, f32, f32)> { pub fn take_pending_popup(&self) -> Option<(PopupRequest, f32, f32)> {
self.pending_popup self.state
.borrow_mut() .borrow_mut()
.pending_popup
.take() .take()
.map(|p| (p.request, p.width, p.height)) .map(|p| (p.request, p.width, p.height))
} }
@ -145,7 +152,7 @@ impl PopupManager {
} }
pub fn close_current_popup(&self) { pub fn close_current_popup(&self) {
let key = self.current_popup_key.borrow_mut().take(); let key = self.state.borrow_mut().current_popup_key.take();
if let Some(key) = key { if let Some(key) = key {
self.destroy_popup(key); self.destroy_popup(key);
} }
@ -153,7 +160,7 @@ impl PopupManager {
#[must_use] #[must_use]
pub fn current_popup_key(&self) -> Option<usize> { pub fn current_popup_key(&self) -> Option<usize> {
*self.current_popup_key.borrow() self.state.borrow().current_popup_key
} }
pub fn create_popup( pub fn create_popup(
@ -235,14 +242,15 @@ impl PopupManager {
params.height, params.height,
))); )));
let key = self.popups.borrow_mut().insert(ActivePopup { let mut state = self.state.borrow_mut();
let key = state.popups.insert(ActivePopup {
surface: popup_surface, surface: popup_surface,
window: Rc::clone(&popup_window), window: Rc::clone(&popup_window),
request, request,
last_serial: params.last_pointer_serial, last_serial: params.last_pointer_serial,
}); });
popup_window.set_popup_manager(Rc::downgrade(self), key); popup_window.set_popup_manager(Rc::downgrade(self), key);
*self.current_popup_key.borrow_mut() = Some(key); state.current_popup_key = Some(key);
info!("Popup window created successfully with key {key}"); info!("Popup window created successfully with key {key}");
@ -250,7 +258,8 @@ impl PopupManager {
} }
pub fn render_popups(&self) -> Result<()> { pub fn render_popups(&self) -> Result<()> {
for (_key, popup) in self.popups.borrow().iter() { let state = self.state.borrow();
for (_key, popup) in &state.popups {
popup.window.render_frame_if_dirty()?; popup.window.render_frame_if_dirty()?;
} }
Ok(()) Ok(())
@ -261,14 +270,16 @@ impl PopupManager {
} }
pub fn mark_all_popups_dirty(&self) { pub fn mark_all_popups_dirty(&self) {
for (_key, popup) in self.popups.borrow().iter() { let state = self.state.borrow();
for (_key, popup) in &state.popups {
popup.window.request_redraw(); popup.window.request_redraw();
} }
} }
pub fn find_popup_key_by_surface_id(&self, surface_id: &ObjectId) -> Option<usize> { pub fn find_popup_key_by_surface_id(&self, surface_id: &ObjectId) -> Option<usize> {
self.popups self.state
.borrow() .borrow()
.popups
.iter() .iter()
.find_map(|(key, popup)| (popup.surface.surface.id() == *surface_id).then_some(key)) .find_map(|(key, popup)| (popup.surface.surface.id() == *surface_id).then_some(key))
} }
@ -277,7 +288,7 @@ impl PopupManager {
&self, &self,
fractional_scale_id: &ObjectId, fractional_scale_id: &ObjectId,
) -> Option<usize> { ) -> Option<usize> {
self.popups.borrow().iter().find_map(|(key, popup)| { self.state.borrow().popups.iter().find_map(|(key, popup)| {
popup popup
.surface .surface
.fractional_scale .fractional_scale
@ -288,14 +299,15 @@ impl PopupManager {
} }
pub fn get_popup_window(&self, key: usize) -> Option<Rc<PopupWindow>> { pub fn get_popup_window(&self, key: usize) -> Option<Rc<PopupWindow>> {
self.popups self.state
.borrow() .borrow()
.popups
.get(key) .get(key)
.map(|popup| Rc::clone(&popup.window)) .map(|popup| Rc::clone(&popup.window))
} }
pub fn destroy_popup(&self, key: usize) { pub fn destroy_popup(&self, key: usize) {
if let Some(popup) = self.popups.borrow_mut().try_remove(key) { if let Some(popup) = self.state.borrow_mut().popups.try_remove(key) {
info!("Destroying popup with key {key}"); info!("Destroying popup with key {key}");
popup.surface.destroy(); popup.surface.destroy();
@ -303,20 +315,21 @@ impl PopupManager {
} }
pub fn find_popup_key_by_xdg_popup_id(&self, xdg_popup_id: &ObjectId) -> Option<usize> { pub fn find_popup_key_by_xdg_popup_id(&self, xdg_popup_id: &ObjectId) -> Option<usize> {
self.popups self.state
.borrow() .borrow()
.popups
.iter() .iter()
.find_map(|(key, popup)| (popup.surface.xdg_popup.id() == *xdg_popup_id).then_some(key)) .find_map(|(key, popup)| (popup.surface.xdg_popup.id() == *xdg_popup_id).then_some(key))
} }
pub fn find_popup_key_by_xdg_surface_id(&self, xdg_surface_id: &ObjectId) -> Option<usize> { pub fn find_popup_key_by_xdg_surface_id(&self, xdg_surface_id: &ObjectId) -> Option<usize> {
self.popups.borrow().iter().find_map(|(key, popup)| { self.state.borrow().popups.iter().find_map(|(key, popup)| {
(popup.surface.xdg_surface.id() == *xdg_surface_id).then_some(key) (popup.surface.xdg_surface.id() == *xdg_surface_id).then_some(key)
}) })
} }
pub fn update_popup_viewport(&self, key: usize, logical_width: i32, logical_height: i32) { pub fn update_popup_viewport(&self, key: usize, logical_width: i32, logical_height: i32) {
if let Some(popup) = self.popups.borrow().get(key) { if let Some(popup) = self.state.borrow().popups.get(key) {
popup popup
.surface .surface
.update_viewport_size(logical_width, logical_height); .update_viewport_size(logical_width, logical_height);
@ -324,14 +337,15 @@ impl PopupManager {
} }
pub fn get_popup_info(&self, key: usize) -> Option<(PopupRequest, u32)> { pub fn get_popup_info(&self, key: usize) -> Option<(PopupRequest, u32)> {
self.popups self.state
.borrow() .borrow()
.popups
.get(key) .get(key)
.map(|popup| (popup.request.clone(), popup.last_serial)) .map(|popup| (popup.request.clone(), popup.last_serial))
} }
pub fn mark_popup_configured(&self, key: usize) { pub fn mark_popup_configured(&self, key: usize) {
if let Some(popup) = self.popups.borrow().get(key) { if let Some(popup) = self.state.borrow().popups.get(key) {
popup.window.mark_configured(); popup.window.mark_configured();
} }
} }

View file

@ -42,18 +42,6 @@ impl PopupState {
} }
} }
pub fn clear_active_window(&mut self) {
if let Some(popup_service) = &self.popup_service {
popup_service.clear_active_window();
}
}
pub fn clear_active_window_if_popup(&mut self, popup_key: usize) {
if let Some(popup_service) = &self.popup_service {
popup_service.clear_active_window_if_popup(popup_key);
}
}
pub const fn popup_service(&self) -> &Option<Rc<PopupService>> { pub const fn popup_service(&self) -> &Option<Rc<PopupService>> {
&self.popup_service &self.popup_service
} }

View file

@ -1,10 +1,10 @@
use log::info; use log::info;
use slint::LogicalPosition; use slint::LogicalPosition;
use std::cell::RefCell; use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
pub struct SharedPointerSerial { pub struct SharedPointerSerial {
serial: RefCell<u32>, serial: Cell<u32>,
} }
impl Default for SharedPointerSerial { impl Default for SharedPointerSerial {
@ -16,16 +16,16 @@ impl Default for SharedPointerSerial {
impl SharedPointerSerial { impl SharedPointerSerial {
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
serial: RefCell::new(0), serial: Cell::new(0),
} }
} }
pub fn update(&self, serial: u32) { pub fn update(&self, serial: u32) {
*self.serial.borrow_mut() = serial; self.serial.set(serial);
} }
pub fn get(&self) -> u32 { pub fn get(&self) -> u32 {
*self.serial.borrow() self.serial.get()
} }
} }

View file

@ -1,4 +1,5 @@
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell;
use super::surface_builder::WindowStateBuilder; use super::surface_builder::WindowStateBuilder;
use super::component_state::ComponentState; use super::component_state::ComponentState;
use super::rendering_state::RenderingState; use super::rendering_state::RenderingState;
@ -18,6 +19,7 @@ use crate::errors::{LayerShikaError, Result};
use core::result::Result as CoreResult; use core::result::Result as CoreResult;
use layer_shika_domain::errors::DomainError; use layer_shika_domain::errors::DomainError;
use layer_shika_domain::ports::windowing::RuntimeStatePort; use layer_shika_domain::ports::windowing::RuntimeStatePort;
use layer_shika_domain::value_objects::popup_request::PopupHandle;
use slint::{LogicalPosition, PhysicalSize}; use slint::{LogicalPosition, PhysicalSize};
use slint::platform::WindowEvent; use slint::platform::WindowEvent;
use slint_interpreter::{ComponentInstance, CompilationResult}; use slint_interpreter::{ComponentInstance, CompilationResult};
@ -31,6 +33,8 @@ pub struct WindowState {
interaction: InteractionState, interaction: InteractionState,
popup: PopupState, popup: PopupState,
output_size: PhysicalSize, output_size: PhysicalSize,
active_popup_key: RefCell<Option<usize>>,
main_surface: Rc<WlSurface>,
} }
impl WindowState { impl WindowState {
@ -112,6 +116,8 @@ impl WindowState {
interaction, interaction,
popup, popup,
output_size: builder.output_size.unwrap_or_default(), output_size: builder.output_size.unwrap_or_default(),
active_popup_key: RefCell::new(None),
main_surface: surface_rc,
}) })
} }
@ -206,12 +212,39 @@ impl WindowState {
self.popup.set_popup_manager(popup_manager); self.popup.set_popup_manager(popup_manager);
} }
pub fn find_window_for_surface(&mut self, surface: &WlSurface) { pub fn set_entered_surface(&self, surface: &WlSurface) {
self.interaction.find_window_for_surface(surface); if let Some(popup_service) = self.popup.popup_service() {
if let Some(popup_key) = popup_service
.manager()
.find_popup_key_by_surface_id(&surface.id())
{
*self.active_popup_key.borrow_mut() = Some(popup_key);
return;
}
}
*self.active_popup_key.borrow_mut() = None;
}
pub fn clear_entered_surface(&self) {
*self.active_popup_key.borrow_mut() = None;
} }
pub fn dispatch_to_active_window(&self, event: WindowEvent) { pub fn dispatch_to_active_window(&self, event: WindowEvent) {
self.interaction.dispatch_to_active_window(event); let active_popup = *self.active_popup_key.borrow();
if let Some(popup_key) = active_popup {
if let Some(popup_service) = self.popup.popup_service() {
if let Some(popup_window) =
popup_service.get_popup_window(PopupHandle::new(popup_key))
{
popup_window.dispatch_event(event);
return;
}
}
}
self.interaction
.dispatch_to_active_window(event, &self.main_surface);
} }
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
@ -233,14 +266,6 @@ impl WindowState {
.update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths); .update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths);
} }
pub fn clear_active_window(&mut self) {
self.popup.clear_active_window();
}
pub fn clear_active_window_if_popup(&mut self, popup_key: usize) {
self.popup.clear_active_window_if_popup(popup_key);
}
pub fn popup_service(&self) -> &Option<Rc<PopupService>> { pub fn popup_service(&self) -> &Option<Rc<PopupService>> {
self.popup.popup_service() self.popup.popup_service()
} }