mirror of
				https://codeberg.org/waydeer/layer-shika.git
				synced 2025-11-04 03:04:23 +00:00 
			
		
		
		
	feat: add popup positioning
This commit is contained in:
		
							parent
							
								
									18d1391dee
								
							
						
					
					
						commit
						ec08429413
					
				
					 5 changed files with 77 additions and 15 deletions
				
			
		| 
						 | 
					@ -5,7 +5,10 @@ pub mod rendering;
 | 
				
			||||||
pub mod wayland;
 | 
					pub mod wayland;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use rendering::femtovg::popup_window::PopupWindow;
 | 
					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 mod platform {
 | 
				
			||||||
    pub use slint;
 | 
					    pub use slint;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 {
 | 
					pub struct CustomSlintPlatform {
 | 
				
			||||||
    main_window: Weak<FemtoVGWindow>,
 | 
					    main_window: Weak<FemtoVGWindow>,
 | 
				
			||||||
    popup_creator: RefCell<Option<Rc<PopupCreator>>>,
 | 
					    popup_creator: RefCell<Option<Rc<PopupCreator>>>,
 | 
				
			||||||
    first_call: Cell<bool>,
 | 
					    first_call: Cell<bool>,
 | 
				
			||||||
    last_popup: RefCell<Option<Weak<PopupWindow>>>,
 | 
					    last_popup: RefCell<Option<Weak<PopupWindow>>>,
 | 
				
			||||||
 | 
					    popup_position: RefCell<Option<(f32, f32)>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl CustomSlintPlatform {
 | 
					impl CustomSlintPlatform {
 | 
				
			||||||
| 
						 | 
					@ -39,6 +69,7 @@ impl CustomSlintPlatform {
 | 
				
			||||||
            popup_creator: RefCell::new(None),
 | 
					            popup_creator: RefCell::new(None),
 | 
				
			||||||
            first_call: Cell::new(true),
 | 
					            first_call: Cell::new(true),
 | 
				
			||||||
            last_popup: RefCell::new(None),
 | 
					            last_popup: RefCell::new(None),
 | 
				
			||||||
 | 
					            popup_position: RefCell::new(None),
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CURRENT_PLATFORM.with(|current| {
 | 
					        CURRENT_PLATFORM.with(|current| {
 | 
				
			||||||
| 
						 | 
					@ -68,6 +99,19 @@ impl CustomSlintPlatform {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        *self.last_popup.borrow_mut() = None;
 | 
					        *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 {
 | 
					impl Platform for CustomSlintPlatform {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,9 @@
 | 
				
			||||||
use crate::errors::{LayerShikaError, Result};
 | 
					use crate::errors::{LayerShikaError, Result};
 | 
				
			||||||
use crate::rendering::egl::context::EGLContext;
 | 
					use crate::rendering::egl::context::EGLContext;
 | 
				
			||||||
use crate::rendering::femtovg::popup_window::PopupWindow;
 | 
					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 log::info;
 | 
				
			||||||
use slab::Slab;
 | 
					use slab::Slab;
 | 
				
			||||||
use slint::{platform::femtovg_renderer::FemtoVGRenderer, PhysicalSize, WindowSize};
 | 
					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 scale_factor = *self.current_scale_factor.borrow();
 | 
				
			||||||
        let output_size = *self.current_output_size.borrow();
 | 
					        let output_size = *self.current_output_size.borrow();
 | 
				
			||||||
        info!(
 | 
					        info!(
 | 
				
			||||||
| 
						 | 
					@ -120,7 +132,7 @@ impl PopupManager {
 | 
				
			||||||
            fractional_scale_manager: self.context.fractional_scale_manager.as_ref(),
 | 
					            fractional_scale_manager: self.context.fractional_scale_manager.as_ref(),
 | 
				
			||||||
            viewporter: self.context.viewporter.as_ref(),
 | 
					            viewporter: self.context.viewporter.as_ref(),
 | 
				
			||||||
            queue_handle,
 | 
					            queue_handle,
 | 
				
			||||||
            position: slint::LogicalPosition::new(0.0, 0.0),
 | 
					            position: pointer_position,
 | 
				
			||||||
            size: popup_size,
 | 
					            size: popup_size,
 | 
				
			||||||
            scale_factor,
 | 
					            scale_factor,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,23 +108,23 @@ impl PopupSurface {
 | 
				
			||||||
            .xdg_wm_base
 | 
					            .xdg_wm_base
 | 
				
			||||||
            .create_positioner(params.queue_handle, ());
 | 
					            .create_positioner(params.queue_handle, ());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let x = (params.position.x * params.scale_factor) as i32;
 | 
					        let x = params.position.x as i32;
 | 
				
			||||||
        let y = (params.position.y * params.scale_factor) as i32;
 | 
					        let y = params.position.y as i32;
 | 
				
			||||||
        let width = params.size.width as i32;
 | 
					
 | 
				
			||||||
        let height = params.size.height 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_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_anchor(Anchor::TopLeft);
 | 
				
			||||||
        positioner.set_gravity(Gravity::BottomRight);
 | 
					        positioner.set_gravity(Gravity::BottomRight);
 | 
				
			||||||
        positioner.set_constraint_adjustment(
 | 
					        positioner.set_constraint_adjustment(ConstraintAdjustment::None);
 | 
				
			||||||
            ConstraintAdjustment::SlideX
 | 
					 | 
				
			||||||
                | ConstraintAdjustment::SlideY
 | 
					 | 
				
			||||||
                | ConstraintAdjustment::FlipX
 | 
					 | 
				
			||||||
                | ConstraintAdjustment::FlipY
 | 
					 | 
				
			||||||
                | ConstraintAdjustment::ResizeX
 | 
					 | 
				
			||||||
                | ConstraintAdjustment::ResizeY,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        positioner
 | 
					        positioner
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,9 @@ pub use builder::LayerShika;
 | 
				
			||||||
pub use layer_shika_adapters::PopupWindow;
 | 
					pub use layer_shika_adapters::PopupWindow;
 | 
				
			||||||
pub use layer_shika_adapters::close_current_popup;
 | 
					pub use layer_shika_adapters::close_current_popup;
 | 
				
			||||||
pub use layer_shika_adapters::platform::{calloop, slint, slint_interpreter};
 | 
					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 use layer_shika_domain::value_objects::anchor::AnchorEdges;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type Result<T> = StdResult<T, Error>;
 | 
					pub type Result<T> = StdResult<T, Error>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue