mirror of
https://codeberg.org/waydeer/layer-shika.git
synced 2025-11-17 23:14:23 +00:00
refactor: display metrics consolidation
This commit is contained in:
parent
a46ba14254
commit
06453367bd
6 changed files with 225 additions and 38 deletions
|
|
@ -60,7 +60,10 @@ impl WaylandWindowingSystem {
|
|||
Rc::clone(&connection),
|
||||
);
|
||||
|
||||
let popup_manager = Rc::new(PopupManager::new(popup_context, state.scale_factor()));
|
||||
let popup_manager = Rc::new(PopupManager::new(
|
||||
popup_context,
|
||||
Rc::clone(state.display_metrics()),
|
||||
));
|
||||
let popup_service = Rc::new(PopupService::new(popup_manager));
|
||||
let shared_serial = Rc::new(SharedPointerSerial::new());
|
||||
|
||||
|
|
|
|||
139
adapters/src/wayland/surfaces/display_metrics.rs
Normal file
139
adapters/src/wayland/surfaces/display_metrics.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use log::info;
|
||||
use slint::PhysicalSize;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
pub trait DisplayMetricsObserver {
|
||||
fn on_scale_factor_changed(&self, new_scale: f32);
|
||||
fn on_output_size_changed(&self, new_size: PhysicalSize);
|
||||
}
|
||||
|
||||
pub struct DisplayMetrics {
|
||||
scale_factor: f32,
|
||||
output_size: PhysicalSize,
|
||||
surface_size: PhysicalSize,
|
||||
has_fractional_scale: bool,
|
||||
observers: RefCell<Vec<Weak<dyn DisplayMetricsObserver>>>,
|
||||
}
|
||||
|
||||
impl DisplayMetrics {
|
||||
#[must_use]
|
||||
pub fn new(scale_factor: f32, has_fractional_scale: bool) -> Self {
|
||||
Self {
|
||||
scale_factor,
|
||||
output_size: PhysicalSize::new(0, 0),
|
||||
surface_size: PhysicalSize::new(0, 0),
|
||||
has_fractional_scale,
|
||||
observers: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_output_size(mut self, output_size: PhysicalSize) -> Self {
|
||||
self.output_size = output_size;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn scale_factor(&self) -> f32 {
|
||||
self.scale_factor
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn output_size(&self) -> PhysicalSize {
|
||||
self.output_size
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn surface_size(&self) -> PhysicalSize {
|
||||
self.surface_size
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn has_fractional_scale(&self) -> bool {
|
||||
self.has_fractional_scale
|
||||
}
|
||||
|
||||
pub fn register_observer(&self, observer: Weak<dyn DisplayMetricsObserver>) {
|
||||
self.observers.borrow_mut().push(observer);
|
||||
self.cleanup_dead_observers();
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
pub fn update_scale_factor(&mut self, scale_120ths: u32) -> f32 {
|
||||
let new_scale_factor = scale_120ths as f32 / 120.0;
|
||||
let old_scale_factor = self.scale_factor;
|
||||
|
||||
if (self.scale_factor - new_scale_factor).abs() > f32::EPSILON {
|
||||
info!(
|
||||
"DisplayMetrics: Updating scale factor from {} to {} ({}x)",
|
||||
old_scale_factor, new_scale_factor, scale_120ths
|
||||
);
|
||||
self.scale_factor = new_scale_factor;
|
||||
self.recalculate_surface_size();
|
||||
self.notify_scale_factor_changed(new_scale_factor);
|
||||
}
|
||||
|
||||
new_scale_factor
|
||||
}
|
||||
|
||||
pub fn update_output_size(&mut self, output_size: PhysicalSize) {
|
||||
if self.output_size != output_size {
|
||||
info!(
|
||||
"DisplayMetrics: Updating output size from {:?} to {:?}",
|
||||
self.output_size, output_size
|
||||
);
|
||||
self.output_size = output_size;
|
||||
self.recalculate_surface_size();
|
||||
self.notify_output_size_changed(output_size);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_surface_size(&mut self, surface_size: PhysicalSize) {
|
||||
self.surface_size = surface_size;
|
||||
}
|
||||
|
||||
#[allow(
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::cast_precision_loss
|
||||
)]
|
||||
fn recalculate_surface_size(&mut self) {
|
||||
if self.output_size.width > 0 && self.output_size.height > 0 && self.scale_factor > 0.0 {
|
||||
self.surface_size = PhysicalSize::new(
|
||||
(self.output_size.width as f32 / self.scale_factor) as u32,
|
||||
(self.output_size.height as f32 / self.scale_factor) as u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_scale_factor_changed(&self, new_scale: f32) {
|
||||
self.observers.borrow_mut().retain(|observer| {
|
||||
if let Some(obs) = observer.upgrade() {
|
||||
obs.on_scale_factor_changed(new_scale);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn notify_output_size_changed(&self, new_size: PhysicalSize) {
|
||||
self.observers.borrow_mut().retain(|observer| {
|
||||
if let Some(obs) = observer.upgrade() {
|
||||
obs.on_output_size_changed(new_size);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn cleanup_dead_observers(&self) {
|
||||
self.observers
|
||||
.borrow_mut()
|
||||
.retain(|obs| obs.upgrade().is_some());
|
||||
}
|
||||
}
|
||||
|
||||
pub type SharedDisplayMetrics = Rc<RefCell<DisplayMetrics>>;
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
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::window_events::{ScaleSource, WindowStateEvent};
|
||||
use layer_shika_domain::value_objects::popup_request::PopupHandle;
|
||||
use log::info;
|
||||
use slint::platform::{WindowAdapter, WindowEvent};
|
||||
use slint::{LogicalPosition, PhysicalSize};
|
||||
use std::cell::Cell;
|
||||
|
|
@ -43,8 +43,7 @@ pub struct EventContext {
|
|||
main_surface_id: ObjectId,
|
||||
popup_service: Option<Rc<PopupService>>,
|
||||
event_bus: EventBus,
|
||||
scale_factor: f32,
|
||||
has_fractional_scale: bool,
|
||||
display_metrics: SharedDisplayMetrics,
|
||||
current_pointer_position: LogicalPosition,
|
||||
last_pointer_serial: u32,
|
||||
shared_pointer_serial: Option<Rc<SharedPointerSerial>>,
|
||||
|
|
@ -55,16 +54,14 @@ impl EventContext {
|
|||
pub fn new(
|
||||
main_window: Rc<FemtoVGWindow>,
|
||||
main_surface_id: ObjectId,
|
||||
scale_factor: f32,
|
||||
has_fractional_scale: bool,
|
||||
display_metrics: SharedDisplayMetrics,
|
||||
) -> Self {
|
||||
Self {
|
||||
main_window,
|
||||
main_surface_id,
|
||||
popup_service: None,
|
||||
event_bus: EventBus::new(),
|
||||
scale_factor,
|
||||
has_fractional_scale,
|
||||
display_metrics,
|
||||
current_pointer_position: LogicalPosition::new(0.0, 0.0),
|
||||
last_pointer_serial: 0,
|
||||
shared_pointer_serial: None,
|
||||
|
|
@ -95,19 +92,21 @@ impl EventContext {
|
|||
.map(|service| Rc::clone(service.manager()))
|
||||
}
|
||||
|
||||
pub const fn scale_factor(&self) -> f32 {
|
||||
self.scale_factor
|
||||
#[must_use]
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
self.display_metrics.borrow().scale_factor()
|
||||
}
|
||||
|
||||
pub const fn display_metrics(&self) -> &SharedDisplayMetrics {
|
||||
&self.display_metrics
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
pub fn update_scale_factor(&mut self, scale_120ths: u32) -> f32 {
|
||||
let new_scale_factor = scale_120ths as f32 / 120.0;
|
||||
let old_scale_factor = self.scale_factor;
|
||||
info!(
|
||||
"Updating scale factor from {} to {} ({}x)",
|
||||
old_scale_factor, new_scale_factor, scale_120ths
|
||||
);
|
||||
self.scale_factor = new_scale_factor;
|
||||
let new_scale_factor = self
|
||||
.display_metrics
|
||||
.borrow_mut()
|
||||
.update_scale_factor(scale_120ths);
|
||||
|
||||
if let Some(popup_service) = &self.popup_service {
|
||||
popup_service.update_scale_factor(new_scale_factor);
|
||||
|
|
@ -128,12 +127,15 @@ impl EventContext {
|
|||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
|
||||
let logical_position = if self.has_fractional_scale {
|
||||
let has_fractional_scale = self.display_metrics.borrow().has_fractional_scale();
|
||||
let scale_factor = self.display_metrics.borrow().scale_factor();
|
||||
|
||||
let logical_position = if has_fractional_scale {
|
||||
LogicalPosition::new(physical_x as f32, physical_y as f32)
|
||||
} else {
|
||||
LogicalPosition::new(
|
||||
(physical_x / f64::from(self.scale_factor)) as f32,
|
||||
(physical_y / f64::from(self.scale_factor)) as f32,
|
||||
(physical_x / f64::from(scale_factor)) as f32,
|
||||
(physical_y / f64::from(scale_factor)) as f32,
|
||||
)
|
||||
};
|
||||
self.current_pointer_position = logical_position;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod component_state;
|
||||
pub mod dimensions;
|
||||
pub mod display_metrics;
|
||||
pub mod event_bus;
|
||||
pub mod event_context;
|
||||
pub mod event_router;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::errors::{LayerShikaError, Result};
|
||||
use crate::rendering::egl::context::EGLContext;
|
||||
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;
|
||||
|
|
@ -101,19 +102,17 @@ struct PendingPopup {
|
|||
|
||||
struct PopupManagerState {
|
||||
popups: HashMap<PopupId, ActivePopup>,
|
||||
scale_factor: f32,
|
||||
output_size: PhysicalSize,
|
||||
display_metrics: SharedDisplayMetrics,
|
||||
current_popup_id: Option<PopupId>,
|
||||
pending_popup: Option<PendingPopup>,
|
||||
id_generator: usize,
|
||||
}
|
||||
|
||||
impl PopupManagerState {
|
||||
fn new(initial_scale_factor: f32) -> Self {
|
||||
fn new(display_metrics: SharedDisplayMetrics) -> Self {
|
||||
Self {
|
||||
popups: HashMap::new(),
|
||||
scale_factor: initial_scale_factor,
|
||||
output_size: PhysicalSize::new(0, 0),
|
||||
display_metrics,
|
||||
current_popup_id: None,
|
||||
pending_popup: None,
|
||||
id_generator: 0,
|
||||
|
|
@ -128,10 +127,10 @@ pub struct PopupManager {
|
|||
|
||||
impl PopupManager {
|
||||
#[must_use]
|
||||
pub fn new(context: PopupContext, initial_scale_factor: f32) -> Self {
|
||||
pub fn new(context: PopupContext, display_metrics: SharedDisplayMetrics) -> Self {
|
||||
Self {
|
||||
context,
|
||||
state: RefCell::new(PopupManagerState::new(initial_scale_factor)),
|
||||
state: RefCell::new(PopupManagerState::new(display_metrics)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,20 +153,34 @@ impl PopupManager {
|
|||
|
||||
#[must_use]
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
self.state.borrow().scale_factor
|
||||
self.state.borrow().display_metrics.borrow().scale_factor()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn output_size(&self) -> PhysicalSize {
|
||||
self.state.borrow().output_size
|
||||
self.state.borrow().display_metrics.borrow().output_size()
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||
pub fn update_scale_factor(&self, scale_factor: f32) {
|
||||
self.state.borrow_mut().scale_factor = scale_factor;
|
||||
let scale_120ths = (scale_factor * 120.0) as u32;
|
||||
self.state
|
||||
.borrow()
|
||||
.display_metrics
|
||||
.borrow_mut()
|
||||
.update_scale_factor(scale_120ths);
|
||||
|
||||
for popup in self.state.borrow().popups.values() {
|
||||
popup.window.set_scale_factor(scale_factor);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_output_size(&self, output_size: PhysicalSize) {
|
||||
self.state.borrow_mut().output_size = output_size;
|
||||
self.state
|
||||
.borrow()
|
||||
.display_metrics
|
||||
.borrow_mut()
|
||||
.update_output_size(output_size);
|
||||
}
|
||||
|
||||
pub fn close_current_popup(&self) {
|
||||
|
|
@ -390,3 +403,16 @@ impl PopupManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayMetricsObserver for PopupManager {
|
||||
fn on_scale_factor_changed(&self, new_scale: f32) {
|
||||
info!("PopupManager received scale factor change: {}", new_scale);
|
||||
for popup in self.state.borrow().popups.values() {
|
||||
popup.window.set_scale_factor(new_scale);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_output_size_changed(&self, new_size: PhysicalSize) {
|
||||
info!("PopupManager received output size change: {:?}", new_size);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use super::rendering_state::RenderingState;
|
|||
use super::event_context::{EventContext, SharedPointerSerial};
|
||||
use super::popup_manager::PopupManager;
|
||||
use super::window_renderer::WindowRendererParams;
|
||||
use super::display_metrics::{DisplayMetrics, SharedDisplayMetrics};
|
||||
use crate::wayland::managed_proxies::{
|
||||
ManagedWlPointer, ManagedWlSurface, ManagedZwlrLayerSurfaceV1,
|
||||
ManagedWpFractionalScaleV1, ManagedWpViewport,
|
||||
|
|
@ -28,9 +29,9 @@ pub struct WindowState {
|
|||
component: ComponentState,
|
||||
rendering: RenderingState,
|
||||
event_context: EventContext,
|
||||
display_metrics: SharedDisplayMetrics,
|
||||
#[allow(dead_code)]
|
||||
pointer: ManagedWlPointer,
|
||||
output_size: PhysicalSize,
|
||||
active_popup_key: RefCell<Option<usize>>,
|
||||
main_surface: Rc<WlSurface>,
|
||||
}
|
||||
|
|
@ -90,11 +91,16 @@ impl WindowState {
|
|||
let size = builder.size.unwrap_or_default();
|
||||
|
||||
let main_surface_id = (*surface_rc).id();
|
||||
|
||||
let display_metrics = Rc::new(RefCell::new(
|
||||
DisplayMetrics::new(builder.scale_factor, has_fractional_scale)
|
||||
.with_output_size(builder.output_size.unwrap_or_default()),
|
||||
));
|
||||
|
||||
let event_context = EventContext::new(
|
||||
Rc::clone(&window),
|
||||
main_surface_id,
|
||||
builder.scale_factor,
|
||||
has_fractional_scale,
|
||||
Rc::clone(&display_metrics),
|
||||
);
|
||||
|
||||
let rendering = RenderingState::new(WindowRendererParams {
|
||||
|
|
@ -112,8 +118,8 @@ impl WindowState {
|
|||
component,
|
||||
rendering,
|
||||
event_context,
|
||||
display_metrics,
|
||||
pointer,
|
||||
output_size: builder.output_size.unwrap_or_default(),
|
||||
active_popup_key: RefCell::new(None),
|
||||
main_surface: surface_rc,
|
||||
})
|
||||
|
|
@ -151,12 +157,14 @@ impl WindowState {
|
|||
}
|
||||
|
||||
pub fn set_output_size(&mut self, output_size: PhysicalSize) {
|
||||
self.output_size = output_size;
|
||||
self.display_metrics
|
||||
.borrow_mut()
|
||||
.update_output_size(output_size);
|
||||
self.event_context.update_output_size(output_size);
|
||||
}
|
||||
|
||||
pub const fn output_size(&self) -> PhysicalSize {
|
||||
self.output_size
|
||||
pub fn output_size(&self) -> PhysicalSize {
|
||||
self.display_metrics.borrow().output_size()
|
||||
}
|
||||
|
||||
pub const fn component_instance(&self) -> &ComponentInstance {
|
||||
|
|
@ -186,6 +194,10 @@ impl WindowState {
|
|||
self.event_context.scale_factor()
|
||||
}
|
||||
|
||||
pub const fn display_metrics(&self) -> &SharedDisplayMetrics {
|
||||
&self.display_metrics
|
||||
}
|
||||
|
||||
pub fn last_pointer_serial(&self) -> u32 {
|
||||
self.event_context.last_pointer_serial()
|
||||
}
|
||||
|
|
@ -203,6 +215,10 @@ impl WindowState {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue