refactor: surface individual mutable fields to single interior mut pattern

This commit is contained in:
drendog 2025-11-02 09:52:15 +01:00
parent 5e162850e9
commit 9e3029c242
Signed by: dwenya
GPG key ID: 8DD77074645332D0
2 changed files with 83 additions and 60 deletions

View file

@ -171,7 +171,7 @@ impl Dispatch<WlPointer, ()> for WindowState {
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.find_window_for_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 });
} }
@ -182,7 +182,7 @@ impl Dispatch<WlPointer, ()> for WindowState {
.. ..
} => { } => {
state.set_current_pointer_position(surface_x, surface_y); state.set_current_pointer_position(surface_x, surface_y);
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 });
} }
@ -198,7 +198,7 @@ impl Dispatch<WlPointer, ()> for WindowState {
.. ..
} => { } => {
state.set_last_pointer_serial(serial); state.set_last_pointer_serial(serial);
let position = *state.current_pointer_position(); let position = state.current_pointer_position();
let event = match button_state { let event = match button_state {
WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed { WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed {
button: PointerEventButton::Left, button: PointerEventButton::Left,

View file

@ -60,6 +60,33 @@ enum ActiveWindow {
Popup(usize), Popup(usize),
} }
struct MutableWindowState {
size: PhysicalSize,
logical_size: PhysicalSize,
output_size: PhysicalSize,
current_pointer_position: LogicalPosition,
last_pointer_serial: u32,
shared_pointer_serial: Option<Rc<SharedPointerSerial>>,
scale_factor: f32,
active_window: Option<ActiveWindow>,
}
impl MutableWindowState {
#[allow(clippy::cast_possible_truncation)]
fn set_pointer_position(&mut self, physical_x: f64, physical_y: f64, fractional_scale: bool) {
let logical_position = if fractional_scale {
LogicalPosition::new(physical_x as f32, physical_y as f32)
} else {
let scale_factor = self.scale_factor;
LogicalPosition::new(
(physical_x / f64::from(scale_factor)) as f32,
(physical_y / f64::from(scale_factor)) as f32,
)
};
self.current_pointer_position = logical_position;
}
}
pub struct WindowState { pub struct WindowState {
component_instance: ComponentInstance, component_instance: ComponentInstance,
viewport: Option<ManagedWpViewport>, viewport: Option<ManagedWpViewport>,
@ -68,18 +95,11 @@ pub struct WindowState {
surface: ManagedWlSurface, surface: ManagedWlSurface,
#[allow(dead_code)] #[allow(dead_code)]
pointer: ManagedWlPointer, pointer: ManagedWlPointer,
size: PhysicalSize,
logical_size: PhysicalSize,
output_size: PhysicalSize,
window: Rc<FemtoVGWindow>, window: Rc<FemtoVGWindow>,
current_pointer_position: LogicalPosition,
last_pointer_serial: u32,
shared_pointer_serial: Option<Rc<SharedPointerSerial>>,
scale_factor: f32,
height: u32, height: u32,
exclusive_zone: i32, exclusive_zone: i32,
popup_manager: Option<Rc<PopupManager>>, popup_manager: Option<Rc<PopupManager>>,
active_window: Option<ActiveWindow>, mutable_state: RefCell<MutableWindowState>,
} }
impl WindowState { impl WindowState {
@ -145,18 +165,20 @@ impl WindowState {
layer_surface, layer_surface,
surface, surface,
pointer, pointer,
size: builder.size.unwrap_or_default(),
logical_size: PhysicalSize::default(),
output_size: builder.output_size.unwrap_or_default(),
window, window,
current_pointer_position: LogicalPosition::default(),
last_pointer_serial: 0,
shared_pointer_serial: None,
scale_factor: builder.scale_factor,
height: builder.height, height: builder.height,
exclusive_zone: builder.exclusive_zone, exclusive_zone: builder.exclusive_zone,
popup_manager: None, popup_manager: None,
active_window: None, mutable_state: RefCell::new(MutableWindowState {
size: builder.size.unwrap_or_default(),
logical_size: PhysicalSize::default(),
output_size: builder.output_size.unwrap_or_default(),
current_pointer_position: LogicalPosition::default(),
last_pointer_serial: 0,
shared_pointer_serial: None,
scale_factor: builder.scale_factor,
active_window: None,
}),
}) })
} }
@ -172,9 +194,10 @@ impl WindowState {
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
fn configure_slint_window(&self, dimensions: &SurfaceDimensions, mode: ScalingMode) { fn configure_slint_window(&self, dimensions: &SurfaceDimensions, mode: ScalingMode) {
let state = self.mutable_state.borrow();
match mode { match mode {
ScalingMode::FractionalWithViewport => { ScalingMode::FractionalWithViewport => {
self.window.set_scale_factor(self.scale_factor); self.window.set_scale_factor(state.scale_factor);
self.window self.window
.set_size(slint::WindowSize::Logical(slint::LogicalSize::new( .set_size(slint::WindowSize::Logical(slint::LogicalSize::new(
dimensions.logical_width as f32, dimensions.logical_width as f32,
@ -190,7 +213,7 @@ impl WindowState {
))); )));
} }
ScalingMode::Integer => { ScalingMode::Integer => {
self.window.set_scale_factor(self.scale_factor); self.window.set_scale_factor(state.scale_factor);
self.window self.window
.set_size(slint::WindowSize::Physical(dimensions.physical_size())); .set_size(slint::WindowSize::Physical(dimensions.physical_size()));
} }
@ -226,7 +249,8 @@ impl WindowState {
return; return;
} }
let dimensions = SurfaceDimensions::calculate(width, height, self.scale_factor); let scale_factor = self.scale_factor();
let dimensions = SurfaceDimensions::calculate(width, height, scale_factor);
let scaling_mode = self.determine_scaling_mode(); let scaling_mode = self.determine_scaling_mode();
info!( info!(
@ -235,7 +259,7 @@ impl WindowState {
dimensions.logical_height, dimensions.logical_height,
dimensions.physical_width, dimensions.physical_width,
dimensions.physical_height, dimensions.physical_height,
self.scale_factor, scale_factor,
dimensions.buffer_scale, dimensions.buffer_scale,
scaling_mode scaling_mode
); );
@ -245,31 +269,25 @@ impl WindowState {
info!("Window physical size: {:?}", self.window.size()); info!("Window physical size: {:?}", self.window.size());
self.size = dimensions.physical_size(); let mut state = self.mutable_state.borrow_mut();
self.logical_size = dimensions.logical_size(); state.size = dimensions.physical_size();
state.logical_size = dimensions.logical_size();
self.window.request_redraw(); self.window.request_redraw();
} }
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) { pub fn set_current_pointer_position(&mut self, physical_x: f64, physical_y: f64) {
let logical_position = if self.fractional_scale.is_some() { let has_fractional_scale = self.fractional_scale.is_some();
LogicalPosition::new(physical_x as f32, physical_y as f32) let mut state = self.mutable_state.borrow_mut();
} else { state.set_pointer_position(physical_x, physical_y, has_fractional_scale);
let scale_factor = self.scale_factor;
LogicalPosition::new(
(physical_x / f64::from(scale_factor)) as f32,
(physical_y / f64::from(scale_factor)) as f32,
)
};
self.current_pointer_position = logical_position;
} }
pub const fn size(&self) -> &PhysicalSize { pub fn size(&self) -> PhysicalSize {
&self.size self.mutable_state.borrow().size
} }
pub const fn current_pointer_position(&self) -> &LogicalPosition { pub fn current_pointer_position(&self) -> LogicalPosition {
&self.current_pointer_position self.mutable_state.borrow().current_pointer_position
} }
pub(crate) fn window(&self) -> Rc<FemtoVGWindow> { pub(crate) fn window(&self) -> Rc<FemtoVGWindow> {
@ -285,14 +303,14 @@ impl WindowState {
} }
pub fn set_output_size(&mut self, output_size: PhysicalSize) { pub fn set_output_size(&mut self, output_size: PhysicalSize) {
self.output_size = output_size; self.mutable_state.borrow_mut().output_size = output_size;
if let Some(popup_manager) = &self.popup_manager { if let Some(popup_manager) = &self.popup_manager {
popup_manager.update_output_size(output_size); popup_manager.update_output_size(output_size);
} }
} }
pub const fn output_size(&self) -> &PhysicalSize { pub fn output_size(&self) -> PhysicalSize {
&self.output_size self.mutable_state.borrow().output_size
} }
pub const fn component_instance(&self) -> &ComponentInstance { pub const fn component_instance(&self) -> &ComponentInstance {
@ -306,39 +324,41 @@ impl WindowState {
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
pub fn update_scale_factor(&mut self, scale_120ths: u32) { pub fn update_scale_factor(&mut self, scale_120ths: u32) {
let new_scale_factor = scale_120ths as f32 / 120.0; let new_scale_factor = scale_120ths as f32 / 120.0;
let old_scale_factor = self.scale_factor();
info!( info!(
"Updating scale factor from {} to {} ({}x)", "Updating scale factor from {} to {} ({}x)",
self.scale_factor, new_scale_factor, scale_120ths old_scale_factor, new_scale_factor, scale_120ths
); );
self.scale_factor = new_scale_factor; self.mutable_state.borrow_mut().scale_factor = new_scale_factor;
if let Some(popup_manager) = &self.popup_manager { if let Some(popup_manager) = &self.popup_manager {
popup_manager.update_scale_factor(new_scale_factor); popup_manager.update_scale_factor(new_scale_factor);
} }
let current_logical_size = self.logical_size; let current_logical_size = self.mutable_state.borrow().logical_size;
if current_logical_size.width > 0 && current_logical_size.height > 0 { if current_logical_size.width > 0 && current_logical_size.height > 0 {
self.update_size(current_logical_size.width, current_logical_size.height); self.update_size(current_logical_size.width, current_logical_size.height);
} }
} }
pub const fn scale_factor(&self) -> f32 { pub fn scale_factor(&self) -> f32 {
self.scale_factor self.mutable_state.borrow().scale_factor
} }
pub const fn last_pointer_serial(&self) -> u32 { pub fn last_pointer_serial(&self) -> u32 {
self.last_pointer_serial self.mutable_state.borrow().last_pointer_serial
} }
pub fn set_last_pointer_serial(&mut self, serial: u32) { pub fn set_last_pointer_serial(&mut self, serial: u32) {
self.last_pointer_serial = serial; let mut state = self.mutable_state.borrow_mut();
if let Some(ref shared_serial) = self.shared_pointer_serial { state.last_pointer_serial = serial;
if let Some(ref shared_serial) = state.shared_pointer_serial {
shared_serial.update(serial); shared_serial.update(serial);
} }
} }
pub fn set_shared_pointer_serial(&mut self, shared_serial: Rc<SharedPointerSerial>) { pub fn set_shared_pointer_serial(&mut self, shared_serial: Rc<SharedPointerSerial>) {
self.shared_pointer_serial = Some(shared_serial); self.mutable_state.borrow_mut().shared_pointer_serial = Some(shared_serial);
} }
pub fn set_popup_manager(&mut self, popup_manager: Rc<PopupManager>) { pub fn set_popup_manager(&mut self, popup_manager: Rc<PopupManager>) {
@ -349,22 +369,24 @@ impl WindowState {
let surface_id = surface.id(); let surface_id = surface.id();
if (**self.surface.inner()).id() == surface_id { if (**self.surface.inner()).id() == surface_id {
self.active_window = Some(ActiveWindow::Main); self.mutable_state.borrow_mut().active_window = Some(ActiveWindow::Main);
return; return;
} }
if let Some(popup_manager) = &self.popup_manager { if let Some(popup_manager) = &self.popup_manager {
if let Some(popup_key) = popup_manager.find_popup_key_by_surface_id(&surface_id) { if let Some(popup_key) = popup_manager.find_popup_key_by_surface_id(&surface_id) {
self.active_window = Some(ActiveWindow::Popup(popup_key)); self.mutable_state.borrow_mut().active_window =
Some(ActiveWindow::Popup(popup_key));
return; return;
} }
} }
self.active_window = None; self.mutable_state.borrow_mut().active_window = None;
} }
pub fn dispatch_to_active_window(&self, event: WindowEvent) { pub fn dispatch_to_active_window(&self, event: WindowEvent) {
match self.active_window { let active_window = self.mutable_state.borrow().active_window;
match active_window {
Some(ActiveWindow::Main) => { Some(ActiveWindow::Main) => {
self.window.window().dispatch_event(event); self.window.window().dispatch_event(event);
} }
@ -408,13 +430,14 @@ impl WindowState {
} }
} }
pub const fn clear_active_window(&mut self) { pub fn clear_active_window(&mut self) {
self.active_window = None; self.mutable_state.borrow_mut().active_window = None;
} }
pub fn clear_active_window_if_popup(&mut self, popup_key: usize) { pub fn clear_active_window_if_popup(&mut self, popup_key: usize) {
if self.active_window == Some(ActiveWindow::Popup(popup_key)) { let mut state = self.mutable_state.borrow_mut();
self.active_window = None; if state.active_window == Some(ActiveWindow::Popup(popup_key)) {
state.active_window = None;
} }
} }