mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-11-17 23:14:23 +00:00
refactor: consolidate popup managing
This commit is contained in:
parent
ee3204a618
commit
6fb26f15d3
11 changed files with 141 additions and 352 deletions
|
|
@ -269,14 +269,14 @@ impl Dispatch<XdgPopup, ()> for WindowState {
|
|||
} => {
|
||||
info!("XdgPopup Configure: position=({x}, {y}), size=({width}x{height})");
|
||||
|
||||
if let Some(popup_service) = state.popup_service() {
|
||||
if let Some(popup_manager) = state.popup_manager() {
|
||||
let popup_id = xdg_popup.id();
|
||||
if let Some(handle) = popup_service.find_by_xdg_popup(&popup_id) {
|
||||
if let Some(handle) = popup_manager.find_by_xdg_popup(&popup_id) {
|
||||
info!(
|
||||
"Marking popup with handle {handle:?} as configured after XdgPopup::Configure"
|
||||
);
|
||||
popup_service.mark_popup_configured(handle);
|
||||
popup_service.manager().mark_all_popups_dirty();
|
||||
popup_manager.mark_popup_configured(handle.key());
|
||||
popup_manager.mark_all_popups_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -284,14 +284,14 @@ impl Dispatch<XdgPopup, ()> for WindowState {
|
|||
info!("XdgPopup dismissed by compositor");
|
||||
let popup_id = xdg_popup.id();
|
||||
let popup_handle = state
|
||||
.popup_service()
|
||||
.popup_manager()
|
||||
.as_ref()
|
||||
.and_then(|ps| ps.find_by_xdg_popup(&popup_id));
|
||||
.and_then(|pm| pm.find_by_xdg_popup(&popup_id));
|
||||
|
||||
if let Some(handle) = popup_handle {
|
||||
info!("Destroying popup with handle {handle:?}");
|
||||
if let Some(popup_service) = state.popup_service() {
|
||||
let _result = popup_service.close(handle);
|
||||
if let Some(popup_manager) = state.popup_manager() {
|
||||
let _result = popup_manager.close(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -316,9 +316,9 @@ impl Dispatch<XdgSurface, ()> for WindowState {
|
|||
info!("XdgSurface Configure received, sending ack with serial {serial}");
|
||||
xdg_surface.ack_configure(serial);
|
||||
|
||||
if let Some(popup_service) = state.popup_service() {
|
||||
if let Some(popup_manager) = state.popup_manager() {
|
||||
info!("Marking all popups as dirty after Configure");
|
||||
popup_service.manager().mark_all_popups_dirty();
|
||||
popup_manager.mark_all_popups_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,5 @@ pub mod connection;
|
|||
pub mod event_handling;
|
||||
pub mod globals;
|
||||
pub mod managed_proxies;
|
||||
pub mod services;
|
||||
pub mod shell_adapter;
|
||||
pub mod surfaces;
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
pub mod popup_service;
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
use crate::errors::Result;
|
||||
use crate::rendering::femtovg::popup_window::PopupWindow;
|
||||
use crate::wayland::surfaces::popup_manager::PopupId;
|
||||
use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest};
|
||||
use log::info;
|
||||
use slint::PhysicalSize;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use wayland_client::{Proxy, backend::ObjectId, protocol::wl_surface::WlSurface};
|
||||
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||
|
||||
use super::super::surfaces::popup_manager::PopupManager;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ActiveWindow {
|
||||
Main,
|
||||
Popup(usize),
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct PopupService {
|
||||
manager: Rc<PopupManager>,
|
||||
scale_factor: Cell<f32>,
|
||||
}
|
||||
|
||||
impl PopupService {
|
||||
#[must_use]
|
||||
pub fn new(manager: Rc<PopupManager>) -> Self {
|
||||
let scale_factor = manager.scale_factor();
|
||||
Self {
|
||||
manager,
|
||||
scale_factor: Cell::new(scale_factor),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&self, request: PopupRequest, width: f32, height: f32) {
|
||||
self.manager.set_pending_popup(request, width, height);
|
||||
}
|
||||
|
||||
pub fn close(&self, handle: PopupHandle) -> Result<()> {
|
||||
let id = PopupId::from_key(handle.key());
|
||||
self.manager.destroy_popup(id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn close_current(&self) {
|
||||
self.manager.close_current_popup();
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_surface(&self, surface_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.manager
|
||||
.find_popup_key_by_surface_id(surface_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_fractional_scale(&self, fractional_scale_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.manager
|
||||
.find_popup_key_by_fractional_scale_id(fractional_scale_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_xdg_popup(&self, xdg_popup_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.manager
|
||||
.find_popup_key_by_xdg_popup_id(xdg_popup_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_xdg_surface(&self, xdg_surface_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.manager
|
||||
.find_popup_key_by_xdg_surface_id(xdg_surface_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_popup_window(&self, handle: PopupHandle) -> Option<Rc<PopupWindow>> {
|
||||
self.manager.get_popup_window(handle.key())
|
||||
}
|
||||
|
||||
pub fn update_scale_factor(&self, scale_factor: f32) {
|
||||
self.scale_factor.set(scale_factor);
|
||||
self.manager.update_scale_factor(scale_factor);
|
||||
self.manager.mark_all_popups_dirty();
|
||||
}
|
||||
|
||||
pub fn update_output_size(&self, output_size: PhysicalSize) {
|
||||
self.manager.update_output_size(output_size);
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
self.scale_factor.get()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_active_window(
|
||||
&self,
|
||||
surface: &WlSurface,
|
||||
main_surface_id: &ObjectId,
|
||||
) -> ActiveWindow {
|
||||
let surface_id = surface.id();
|
||||
|
||||
if *main_surface_id == surface_id {
|
||||
return ActiveWindow::Main;
|
||||
}
|
||||
|
||||
if let Some(popup_key) = self.manager.find_popup_key_by_surface_id(&surface_id) {
|
||||
return ActiveWindow::Popup(popup_key);
|
||||
}
|
||||
|
||||
ActiveWindow::None
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
pub fn update_scale_for_fractional_scale_object(
|
||||
&self,
|
||||
fractional_scale_proxy: &WpFractionalScaleV1,
|
||||
scale_120ths: u32,
|
||||
) {
|
||||
let fractional_scale_id = fractional_scale_proxy.id();
|
||||
|
||||
if let Some(popup_key) = self
|
||||
.manager
|
||||
.find_popup_key_by_fractional_scale_id(&fractional_scale_id)
|
||||
{
|
||||
if let Some(popup_window) = self.manager.get_popup_window(popup_key) {
|
||||
let new_scale_factor = scale_120ths as f32 / 120.0;
|
||||
info!("Updating popup scale factor to {new_scale_factor} ({scale_120ths}x)");
|
||||
popup_window.set_scale_factor(new_scale_factor);
|
||||
popup_window.request_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_popups(&self) -> Result<()> {
|
||||
self.manager.render_popups()
|
||||
}
|
||||
|
||||
pub fn mark_popup_configured(&self, handle: PopupHandle) {
|
||||
self.manager.mark_popup_configured(handle.key());
|
||||
}
|
||||
|
||||
pub fn update_popup_viewport(
|
||||
&self,
|
||||
handle: PopupHandle,
|
||||
logical_width: i32,
|
||||
logical_height: i32,
|
||||
) {
|
||||
self.manager
|
||||
.update_popup_viewport(handle.key(), logical_width, logical_height);
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_popup_info(&self, handle: PopupHandle) -> Option<(PopupRequest, u32)> {
|
||||
self.manager.get_popup_info(handle.key())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn manager(&self) -> &Rc<PopupManager> {
|
||||
&self.manager
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn has_xdg_shell(&self) -> bool {
|
||||
self.manager.has_xdg_shell()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn current_popup_key(&self) -> Option<usize> {
|
||||
self.manager.current_popup_key()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn take_pending_popup(&self) -> Option<(PopupRequest, f32, f32)> {
|
||||
self.manager.take_pending_popup()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::wayland::{
|
||||
config::{LayerSurfaceParams, WaylandWindowConfig},
|
||||
globals::context::GlobalContext,
|
||||
services::popup_service::PopupService,
|
||||
surfaces::layer_surface::{SurfaceCtx, SurfaceSetupParams},
|
||||
surfaces::popup_manager::{CreatePopupParams, PopupContext, PopupManager},
|
||||
surfaces::{
|
||||
|
|
@ -39,7 +38,7 @@ pub struct WaylandWindowingSystem {
|
|||
connection: Rc<Connection>,
|
||||
event_queue: EventQueue<WindowState>,
|
||||
event_loop: EventLoop<'static, WindowState>,
|
||||
popup_service: Rc<PopupService>,
|
||||
popup_manager: Rc<PopupManager>,
|
||||
}
|
||||
|
||||
impl WaylandWindowingSystem {
|
||||
|
|
@ -64,11 +63,10 @@ impl WaylandWindowingSystem {
|
|||
popup_context,
|
||||
Rc::clone(state.display_metrics()),
|
||||
));
|
||||
let popup_service = Rc::new(PopupService::new(popup_manager));
|
||||
let shared_serial = Rc::new(SharedPointerSerial::new());
|
||||
|
||||
Self::setup_popup_creator(
|
||||
&popup_service,
|
||||
&popup_manager,
|
||||
&platform,
|
||||
&state,
|
||||
&event_queue,
|
||||
|
|
@ -80,12 +78,12 @@ impl WaylandWindowingSystem {
|
|||
connection,
|
||||
event_queue,
|
||||
event_loop,
|
||||
popup_service,
|
||||
popup_manager,
|
||||
})
|
||||
.map(|mut system| {
|
||||
system
|
||||
.state
|
||||
.set_popup_service(Rc::clone(&system.popup_service));
|
||||
.set_popup_manager(Rc::clone(&system.popup_manager));
|
||||
system.state.set_shared_pointer_serial(shared_serial);
|
||||
system
|
||||
})
|
||||
|
|
@ -161,20 +159,20 @@ impl WaylandWindowingSystem {
|
|||
}
|
||||
|
||||
fn setup_popup_creator(
|
||||
popup_service: &Rc<PopupService>,
|
||||
popup_manager: &Rc<PopupManager>,
|
||||
platform: &Rc<CustomSlintPlatform>,
|
||||
state: &WindowState,
|
||||
event_queue: &EventQueue<WindowState>,
|
||||
shared_serial: &Rc<SharedPointerSerial>,
|
||||
) {
|
||||
if !popup_service.has_xdg_shell() {
|
||||
if !popup_manager.has_xdg_shell() {
|
||||
info!("xdg-shell not available, popups will not be supported");
|
||||
return;
|
||||
}
|
||||
|
||||
info!("Setting up popup creator with xdg-shell support");
|
||||
|
||||
let popup_service_clone = Rc::clone(popup_service);
|
||||
let popup_manager_clone = Rc::clone(popup_manager);
|
||||
let layer_surface = state.layer_surface();
|
||||
let queue_handle = event_queue.handle();
|
||||
let serial_holder = Rc::clone(shared_serial);
|
||||
|
|
@ -185,7 +183,7 @@ impl WaylandWindowingSystem {
|
|||
let serial = serial_holder.get();
|
||||
|
||||
let (params, request) = if let Some((request, width, height)) =
|
||||
popup_service_clone.take_pending_popup()
|
||||
popup_manager_clone.take_pending_popup()
|
||||
{
|
||||
log::info!(
|
||||
"Using popup request: component='{}', position=({}, {}), size={}x{}, mode={:?}",
|
||||
|
|
@ -214,8 +212,7 @@ impl WaylandWindowingSystem {
|
|||
));
|
||||
};
|
||||
|
||||
let popup_window = popup_service_clone
|
||||
.manager()
|
||||
let popup_window = popup_manager_clone
|
||||
.create_popup(&queue_handle, &layer_surface, params, request)
|
||||
.map_err(|e| PlatformError::Other(format!("Failed to create popup: {e}")))?;
|
||||
|
||||
|
|
@ -280,12 +277,12 @@ impl WaylandWindowingSystem {
|
|||
|
||||
let event_queue = &mut self.event_queue;
|
||||
let connection = &self.connection;
|
||||
let popup_service = Rc::clone(&self.popup_service);
|
||||
let popup_manager = Rc::clone(&self.popup_manager);
|
||||
|
||||
self.event_loop
|
||||
.run(None, &mut self.state, move |shared_data| {
|
||||
if let Err(e) =
|
||||
Self::process_events(connection, event_queue, shared_data, &popup_service)
|
||||
Self::process_events(connection, event_queue, shared_data, &popup_manager)
|
||||
{
|
||||
error!("Error processing events: {e}");
|
||||
}
|
||||
|
|
@ -315,7 +312,7 @@ impl WaylandWindowingSystem {
|
|||
connection: &Connection,
|
||||
event_queue: &mut EventQueue<WindowState>,
|
||||
shared_data: &mut WindowState,
|
||||
popup_service: &PopupService,
|
||||
popup_manager: &PopupManager,
|
||||
) -> Result<()> {
|
||||
if let Some(guard) = event_queue.prepare_read() {
|
||||
guard
|
||||
|
|
@ -334,7 +331,7 @@ impl WaylandWindowingSystem {
|
|||
message: e.to_string(),
|
||||
})?;
|
||||
|
||||
popup_service
|
||||
popup_manager
|
||||
.render_popups()
|
||||
.map_err(|e| RenderingError::Operation {
|
||||
message: e.to_string(),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
use crate::rendering::femtovg::main_window::FemtoVGWindow;
|
||||
use crate::wayland::services::popup_service::{ActiveWindow, PopupService};
|
||||
use crate::wayland::surfaces::display_metrics::SharedDisplayMetrics;
|
||||
use crate::wayland::surfaces::event_bus::EventBus;
|
||||
use crate::wayland::surfaces::popup_manager::PopupManager;
|
||||
use crate::wayland::surfaces::popup_manager::{ActiveWindow, PopupManager};
|
||||
use crate::wayland::surfaces::window_events::{ScaleSource, WindowStateEvent};
|
||||
use layer_shika_domain::value_objects::popup_request::PopupHandle;
|
||||
use slint::platform::{WindowAdapter, WindowEvent};
|
||||
use slint::{LogicalPosition, PhysicalSize};
|
||||
use std::cell::Cell;
|
||||
|
|
@ -41,7 +39,7 @@ impl SharedPointerSerial {
|
|||
pub struct EventContext {
|
||||
main_window: Rc<FemtoVGWindow>,
|
||||
main_surface_id: ObjectId,
|
||||
popup_service: Option<Rc<PopupService>>,
|
||||
popup_manager: Option<Rc<PopupManager>>,
|
||||
event_bus: EventBus,
|
||||
display_metrics: SharedDisplayMetrics,
|
||||
current_pointer_position: LogicalPosition,
|
||||
|
|
@ -59,7 +57,7 @@ impl EventContext {
|
|||
Self {
|
||||
main_window,
|
||||
main_surface_id,
|
||||
popup_service: None,
|
||||
popup_manager: None,
|
||||
event_bus: EventBus::new(),
|
||||
display_metrics,
|
||||
current_pointer_position: LogicalPosition::new(0.0, 0.0),
|
||||
|
|
@ -76,20 +74,14 @@ impl EventContext {
|
|||
&self.event_bus
|
||||
}
|
||||
|
||||
pub fn set_popup_service(&mut self, popup_service: Rc<PopupService>) {
|
||||
self.popup_service = Some(popup_service);
|
||||
pub fn set_popup_manager(&mut self, popup_manager: Rc<PopupManager>) {
|
||||
self.popup_manager = Some(popup_manager);
|
||||
self.event_bus
|
||||
.publish(&WindowStateEvent::PopupConfigurationChanged);
|
||||
}
|
||||
|
||||
pub const fn popup_service(&self) -> &Option<Rc<PopupService>> {
|
||||
&self.popup_service
|
||||
}
|
||||
|
||||
pub fn popup_manager(&self) -> Option<Rc<PopupManager>> {
|
||||
self.popup_service
|
||||
.as_ref()
|
||||
.map(|service| Rc::clone(service.manager()))
|
||||
pub const fn popup_manager(&self) -> &Option<Rc<PopupManager>> {
|
||||
&self.popup_manager
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
@ -108,8 +100,8 @@ impl EventContext {
|
|||
.borrow_mut()
|
||||
.update_scale_factor(scale_120ths);
|
||||
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service.update_scale_factor(new_scale_factor);
|
||||
if let Some(popup_manager) = &self.popup_manager {
|
||||
popup_manager.update_scale_factor(new_scale_factor);
|
||||
}
|
||||
|
||||
self.event_bus
|
||||
|
|
@ -166,15 +158,13 @@ impl EventContext {
|
|||
}
|
||||
|
||||
pub fn dispatch_to_active_window(&self, event: WindowEvent, surface: &WlSurface) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
match popup_service.get_active_window(surface, &self.main_surface_id) {
|
||||
if let Some(popup_manager) = &self.popup_manager {
|
||||
match popup_manager.get_active_window(surface, &self.main_surface_id) {
|
||||
ActiveWindow::Main => {
|
||||
self.main_window.window().dispatch_event(event);
|
||||
}
|
||||
ActiveWindow::Popup(index) => {
|
||||
if let Some(popup_window) =
|
||||
popup_service.get_popup_window(PopupHandle::new(index))
|
||||
{
|
||||
if let Some(popup_window) = popup_manager.get_popup_window(index) {
|
||||
popup_window.dispatch_event(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -184,8 +174,8 @@ impl EventContext {
|
|||
}
|
||||
|
||||
pub fn update_output_size(&self, output_size: PhysicalSize) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service.update_output_size(output_size);
|
||||
if let Some(popup_manager) = &self.popup_manager {
|
||||
popup_manager.update_output_size(output_size);
|
||||
}
|
||||
|
||||
self.event_bus
|
||||
|
|
@ -197,8 +187,8 @@ impl EventContext {
|
|||
fractional_scale_proxy: &WpFractionalScaleV1,
|
||||
scale_120ths: u32,
|
||||
) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service
|
||||
if let Some(popup_manager) = &self.popup_manager {
|
||||
popup_manager
|
||||
.update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use crate::rendering::femtovg::main_window::FemtoVGWindow;
|
||||
use crate::wayland::services::popup_service::{ActiveWindow, PopupService};
|
||||
use layer_shika_domain::value_objects::popup_request::PopupHandle;
|
||||
use crate::wayland::surfaces::popup_manager::{ActiveWindow, PopupManager};
|
||||
use slint::platform::{WindowAdapter, WindowEvent};
|
||||
use std::rc::Rc;
|
||||
use wayland_client::{backend::ObjectId, protocol::wl_surface::WlSurface};
|
||||
|
||||
pub struct EventRouter {
|
||||
main_window: Rc<FemtoVGWindow>,
|
||||
popup_service: Option<Rc<PopupService>>,
|
||||
popup_manager: Option<Rc<PopupManager>>,
|
||||
main_surface_id: ObjectId,
|
||||
}
|
||||
|
||||
|
|
@ -16,25 +15,23 @@ impl EventRouter {
|
|||
pub const fn new(main_window: Rc<FemtoVGWindow>, main_surface_id: ObjectId) -> Self {
|
||||
Self {
|
||||
main_window,
|
||||
popup_service: None,
|
||||
popup_manager: None,
|
||||
main_surface_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_popup_service(&mut self, popup_service: Rc<PopupService>) {
|
||||
self.popup_service = Some(popup_service);
|
||||
pub fn set_popup_manager(&mut self, popup_manager: Rc<PopupManager>) {
|
||||
self.popup_manager = Some(popup_manager);
|
||||
}
|
||||
|
||||
pub fn dispatch_to_active_window(&self, event: WindowEvent, surface: &WlSurface) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
match popup_service.get_active_window(surface, &self.main_surface_id) {
|
||||
if let Some(popup_manager) = &self.popup_manager {
|
||||
match popup_manager.get_active_window(surface, &self.main_surface_id) {
|
||||
ActiveWindow::Main => {
|
||||
self.main_window.window().dispatch_event(event);
|
||||
}
|
||||
ActiveWindow::Popup(index) => {
|
||||
if let Some(popup_window) =
|
||||
popup_service.get_popup_window(PopupHandle::new(index))
|
||||
{
|
||||
if let Some(popup_window) = popup_manager.get_popup_window(index) {
|
||||
popup_window.dispatch_event(event);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ pub mod event_context;
|
|||
pub mod event_router;
|
||||
pub mod layer_surface;
|
||||
pub mod popup_manager;
|
||||
pub mod popup_state;
|
||||
pub mod popup_surface;
|
||||
pub mod rendering_state;
|
||||
pub mod surface_builder;
|
||||
|
|
|
|||
|
|
@ -4,25 +4,33 @@ use crate::rendering::femtovg::popup_window::PopupWindow;
|
|||
use crate::wayland::surfaces::display_metrics::{DisplayMetricsObserver, SharedDisplayMetrics};
|
||||
use layer_shika_domain::value_objects::popup_config::PopupConfig;
|
||||
use layer_shika_domain::value_objects::popup_positioning_mode::PopupPositioningMode;
|
||||
use layer_shika_domain::value_objects::popup_request::PopupRequest;
|
||||
use layer_shika_domain::value_objects::popup_request::{PopupHandle, PopupRequest};
|
||||
use log::info;
|
||||
use slint::{platform::femtovg_renderer::FemtoVGRenderer, PhysicalSize, WindowSize};
|
||||
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use wayland_client::{
|
||||
backend::ObjectId,
|
||||
protocol::{wl_compositor::WlCompositor, wl_display::WlDisplay, wl_seat::WlSeat},
|
||||
protocol::{wl_compositor::WlCompositor, wl_display::WlDisplay, wl_seat::WlSeat, wl_surface::WlSurface},
|
||||
Connection, Proxy, QueueHandle,
|
||||
};
|
||||
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1;
|
||||
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||
use wayland_protocols::wp::viewporter::client::wp_viewporter::WpViewporter;
|
||||
use wayland_protocols::xdg::shell::client::xdg_wm_base::XdgWmBase;
|
||||
|
||||
use super::popup_surface::PopupSurface;
|
||||
use super::surface_state::WindowState;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ActiveWindow {
|
||||
Main,
|
||||
Popup(usize),
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct PopupId(pub(crate) usize);
|
||||
|
||||
|
|
@ -123,14 +131,17 @@ impl PopupManagerState {
|
|||
pub struct PopupManager {
|
||||
context: PopupContext,
|
||||
state: RefCell<PopupManagerState>,
|
||||
scale_factor: Cell<f32>,
|
||||
}
|
||||
|
||||
impl PopupManager {
|
||||
#[must_use]
|
||||
pub fn new(context: PopupContext, display_metrics: SharedDisplayMetrics) -> Self {
|
||||
let scale_factor = display_metrics.borrow().scale_factor();
|
||||
Self {
|
||||
context,
|
||||
state: RefCell::new(PopupManagerState::new(display_metrics)),
|
||||
scale_factor: Cell::new(scale_factor),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +164,7 @@ impl PopupManager {
|
|||
|
||||
#[must_use]
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
self.state.borrow().display_metrics.borrow().scale_factor()
|
||||
self.scale_factor.get()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
@ -163,6 +174,7 @@ impl PopupManager {
|
|||
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||
pub fn update_scale_factor(&self, scale_factor: f32) {
|
||||
self.scale_factor.set(scale_factor);
|
||||
let scale_120ths = (scale_factor * 120.0) as u32;
|
||||
self.state
|
||||
.borrow()
|
||||
|
|
@ -173,6 +185,7 @@ impl PopupManager {
|
|||
for popup in self.state.borrow().popups.values() {
|
||||
popup.window.set_scale_factor(scale_factor);
|
||||
}
|
||||
self.mark_all_popups_dirty();
|
||||
}
|
||||
|
||||
pub fn update_output_size(&self, output_size: PhysicalSize) {
|
||||
|
|
@ -402,6 +415,77 @@ impl PopupManager {
|
|||
popup.window.mark_configured();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&self, request: PopupRequest, width: f32, height: f32) {
|
||||
self.set_pending_popup(request, width, height);
|
||||
}
|
||||
|
||||
pub fn close(&self, handle: PopupHandle) -> Result<()> {
|
||||
let id = PopupId::from_key(handle.key());
|
||||
self.destroy_popup(id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_surface(&self, surface_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.find_popup_key_by_surface_id(surface_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_fractional_scale(&self, fractional_scale_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.find_popup_key_by_fractional_scale_id(fractional_scale_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_xdg_popup(&self, xdg_popup_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.find_popup_key_by_xdg_popup_id(xdg_popup_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn find_by_xdg_surface(&self, xdg_surface_id: &ObjectId) -> Option<PopupHandle> {
|
||||
self.find_popup_key_by_xdg_surface_id(xdg_surface_id)
|
||||
.map(PopupHandle::new)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_active_window(
|
||||
&self,
|
||||
surface: &WlSurface,
|
||||
main_surface_id: &ObjectId,
|
||||
) -> ActiveWindow {
|
||||
let surface_id = surface.id();
|
||||
|
||||
if *main_surface_id == surface_id {
|
||||
return ActiveWindow::Main;
|
||||
}
|
||||
|
||||
if let Some(popup_key) = self.find_popup_key_by_surface_id(&surface_id) {
|
||||
return ActiveWindow::Popup(popup_key);
|
||||
}
|
||||
|
||||
ActiveWindow::None
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
pub fn update_scale_for_fractional_scale_object(
|
||||
&self,
|
||||
fractional_scale_proxy: &WpFractionalScaleV1,
|
||||
scale_120ths: u32,
|
||||
) {
|
||||
let fractional_scale_id = fractional_scale_proxy.id();
|
||||
|
||||
if let Some(popup_key) = self.find_popup_key_by_fractional_scale_id(&fractional_scale_id) {
|
||||
if let Some(popup_window) = self.get_popup_window(popup_key) {
|
||||
let new_scale_factor = scale_120ths as f32 / 120.0;
|
||||
info!("Updating popup scale factor to {new_scale_factor} ({scale_120ths}x)");
|
||||
popup_window.set_scale_factor(new_scale_factor);
|
||||
popup_window.request_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayMetricsObserver for PopupManager {
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
use crate::wayland::services::popup_service::PopupService;
|
||||
use crate::wayland::surfaces::event_bus::EventBus;
|
||||
use crate::wayland::surfaces::popup_manager::PopupManager;
|
||||
use crate::wayland::surfaces::window_events::WindowStateEvent;
|
||||
use slint::PhysicalSize;
|
||||
use std::rc::Rc;
|
||||
use wayland_protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||
|
||||
pub struct PopupState {
|
||||
popup_service: Option<Rc<PopupService>>,
|
||||
event_bus: EventBus,
|
||||
}
|
||||
|
||||
impl Default for PopupState {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl PopupState {
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
popup_service: None,
|
||||
event_bus: EventBus::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_event_bus(&mut self, event_bus: EventBus) {
|
||||
self.event_bus = event_bus;
|
||||
}
|
||||
|
||||
pub fn set_popup_service(&mut self, popup_service: Rc<PopupService>) {
|
||||
self.popup_service = Some(popup_service);
|
||||
self.event_bus
|
||||
.publish(&WindowStateEvent::PopupConfigurationChanged);
|
||||
}
|
||||
|
||||
pub fn set_popup_manager(&mut self, popup_manager: Rc<PopupManager>) {
|
||||
self.popup_service = Some(Rc::new(PopupService::new(popup_manager)));
|
||||
self.event_bus
|
||||
.publish(&WindowStateEvent::PopupConfigurationChanged);
|
||||
}
|
||||
|
||||
pub fn update_output_size(&self, output_size: PhysicalSize) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service.update_output_size(output_size);
|
||||
}
|
||||
|
||||
self.event_bus
|
||||
.publish(&WindowStateEvent::OutputSizeChanged { output_size });
|
||||
}
|
||||
|
||||
pub fn update_scale_factor(&self, scale_factor: f32) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service.update_scale_factor(scale_factor);
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn popup_service(&self) -> &Option<Rc<PopupService>> {
|
||||
&self.popup_service
|
||||
}
|
||||
|
||||
pub fn popup_manager(&self) -> Option<Rc<PopupManager>> {
|
||||
self.popup_service
|
||||
.as_ref()
|
||||
.map(|service| Rc::clone(service.manager()))
|
||||
}
|
||||
|
||||
pub fn update_scale_for_fractional_scale_object(
|
||||
&self,
|
||||
fractional_scale_proxy: &WpFractionalScaleV1,
|
||||
scale_120ths: u32,
|
||||
) {
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service
|
||||
.update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,13 +11,11 @@ use crate::wayland::managed_proxies::{
|
|||
ManagedWlPointer, ManagedWlSurface, ManagedZwlrLayerSurfaceV1,
|
||||
ManagedWpFractionalScaleV1, ManagedWpViewport,
|
||||
};
|
||||
use crate::wayland::services::popup_service::PopupService;
|
||||
use crate::rendering::femtovg::main_window::FemtoVGWindow;
|
||||
use crate::errors::{LayerShikaError, Result};
|
||||
use core::result::Result as CoreResult;
|
||||
use layer_shika_domain::errors::DomainError;
|
||||
use layer_shika_domain::ports::windowing::RuntimeStatePort;
|
||||
use layer_shika_domain::value_objects::popup_request::PopupHandle;
|
||||
use slint::{LogicalPosition, PhysicalSize};
|
||||
use slint::platform::WindowEvent;
|
||||
use slint_interpreter::{ComponentInstance, CompilationResult};
|
||||
|
|
@ -210,25 +208,17 @@ impl WindowState {
|
|||
self.event_context.set_shared_pointer_serial(shared_serial);
|
||||
}
|
||||
|
||||
pub fn set_popup_service(&mut self, popup_service: Rc<PopupService>) {
|
||||
self.event_context.set_popup_service(popup_service);
|
||||
}
|
||||
|
||||
pub fn set_popup_manager(&mut self, popup_manager: Rc<PopupManager>) {
|
||||
self.display_metrics
|
||||
.borrow()
|
||||
.register_observer(Rc::downgrade(&popup_manager) as _);
|
||||
|
||||
let popup_service = Rc::new(PopupService::new(popup_manager));
|
||||
self.event_context.set_popup_service(popup_service);
|
||||
self.event_context.set_popup_manager(popup_manager);
|
||||
}
|
||||
|
||||
pub fn set_entered_surface(&self, surface: &WlSurface) {
|
||||
if let Some(popup_service) = self.event_context.popup_service() {
|
||||
if let Some(popup_key) = popup_service
|
||||
.manager()
|
||||
.find_popup_key_by_surface_id(&surface.id())
|
||||
{
|
||||
if let Some(popup_manager) = self.event_context.popup_manager() {
|
||||
if let Some(popup_key) = popup_manager.find_popup_key_by_surface_id(&surface.id()) {
|
||||
*self.active_popup_key.borrow_mut() = Some(popup_key);
|
||||
return;
|
||||
}
|
||||
|
|
@ -244,10 +234,8 @@ impl WindowState {
|
|||
let active_popup = *self.active_popup_key.borrow();
|
||||
|
||||
if let Some(popup_key) = active_popup {
|
||||
if let Some(popup_service) = self.event_context.popup_service() {
|
||||
if let Some(popup_window) =
|
||||
popup_service.get_popup_window(PopupHandle::new(popup_key))
|
||||
{
|
||||
if let Some(popup_manager) = self.event_context.popup_manager() {
|
||||
if let Some(popup_window) = popup_manager.get_popup_window(popup_key) {
|
||||
popup_window.dispatch_event(event);
|
||||
return;
|
||||
}
|
||||
|
|
@ -277,11 +265,7 @@ impl WindowState {
|
|||
.update_scale_for_fractional_scale_object(fractional_scale_proxy, scale_120ths);
|
||||
}
|
||||
|
||||
pub fn popup_service(&self) -> &Option<Rc<PopupService>> {
|
||||
self.event_context.popup_service()
|
||||
}
|
||||
|
||||
pub fn popup_manager(&self) -> Option<Rc<PopupManager>> {
|
||||
pub fn popup_manager(&self) -> &Option<Rc<PopupManager>> {
|
||||
self.event_context.popup_manager()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue