fix: popup position clamping to avoid exceeding output boundaries

This commit is contained in:
drendog 2025-11-05 07:42:06 +01:00
parent a5e48f1b9f
commit 11f17a4fc1
Signed by: dwenya
GPG key ID: 8DD77074645332D0
3 changed files with 47 additions and 13 deletions

View file

@ -179,12 +179,21 @@ impl PopupManager {
params.positioning_mode params.positioning_mode
); );
let output_size = self.output_size();
#[allow(clippy::cast_precision_loss)]
let output_logical_size = (
output_size.width as f32 / scale_factor,
output_size.height as f32 / scale_factor,
);
let popup_config = PopupConfig::new( let popup_config = PopupConfig::new(
params.reference_x, params.reference_x,
params.reference_y, params.reference_y,
params.width, params.width,
params.height, params.height,
params.positioning_mode, params.positioning_mode,
output_logical_size.0,
output_logical_size.1,
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]

View file

@ -28,11 +28,7 @@ use std::time::{Duration, Instant};
enum PopupCommand { enum PopupCommand {
Show(PopupRequest), Show(PopupRequest),
Close(PopupHandle), Close(PopupHandle),
Resize { Resize { key: usize, width: f32, height: f32 },
key: usize,
width: f32,
height: f32,
},
} }
pub struct EventLoopHandle { pub struct EventLoopHandle {
@ -142,7 +138,11 @@ impl RuntimeState<'_> {
self.window_state.compilation_result() self.window_state.compilation_result()
} }
pub fn show_popup(&mut self, req: PopupRequest, resize_sender: Option<channel::Sender<PopupCommand>>) -> Result<PopupHandle> { pub fn show_popup(
&mut self,
req: PopupRequest,
resize_sender: Option<channel::Sender<PopupCommand>>,
) -> Result<PopupHandle> {
let compilation_result = self.compilation_result().ok_or_else(|| { let compilation_result = self.compilation_result().ok_or_else(|| {
Error::Domain(DomainError::Configuration { Error::Domain(DomainError::Configuration {
message: "No compilation result available for popup creation".to_string(), message: "No compilation result available for popup creation".to_string(),
@ -229,7 +229,13 @@ impl RuntimeState<'_> {
Ok(()) Ok(())
} }
pub fn resize_popup(&mut self, key: usize, width: f32, height: f32, resize_sender: Option<channel::Sender<PopupCommand>>) -> Result<()> { pub fn resize_popup(
&mut self,
key: usize,
width: f32,
height: f32,
resize_sender: Option<channel::Sender<PopupCommand>>,
) -> Result<()> {
let popup_manager = self let popup_manager = self
.window_state .window_state
.popup_manager() .popup_manager()
@ -416,7 +422,9 @@ impl WindowingSystem {
match command { match command {
PopupCommand::Show(request) => { PopupCommand::Show(request) => {
if let Err(e) = runtime_state.show_popup(request, Some(sender_for_handler.clone())) { if let Err(e) =
runtime_state.show_popup(request, Some(sender_for_handler.clone()))
{
log::error!("Failed to show popup: {}", e); log::error!("Failed to show popup: {}", e);
} }
} }
@ -426,7 +434,12 @@ impl WindowingSystem {
} }
} }
PopupCommand::Resize { key, width, height } => { PopupCommand::Resize { key, width, height } => {
if let Err(e) = runtime_state.resize_popup(key, width, height, Some(sender_for_handler.clone())) { if let Err(e) = runtime_state.resize_popup(
key,
width,
height,
Some(sender_for_handler.clone()),
) {
log::error!("Failed to resize popup: {}", e); log::error!("Failed to resize popup: {}", e);
} }
} }

View file

@ -7,6 +7,8 @@ pub struct PopupConfig {
width: f32, width: f32,
height: f32, height: f32,
positioning_mode: PopupPositioningMode, positioning_mode: PopupPositioningMode,
output_width: f32,
output_height: f32,
} }
impl PopupConfig { impl PopupConfig {
@ -17,6 +19,8 @@ impl PopupConfig {
width: f32, width: f32,
height: f32, height: f32,
positioning_mode: PopupPositioningMode, positioning_mode: PopupPositioningMode,
output_width: f32,
output_height: f32,
) -> Self { ) -> Self {
Self { Self {
reference_x, reference_x,
@ -24,6 +28,8 @@ impl PopupConfig {
width, width,
height, height,
positioning_mode, positioning_mode,
output_width,
output_height,
} }
} }
@ -54,19 +60,25 @@ impl PopupConfig {
#[must_use] #[must_use]
pub fn calculated_top_left_x(&self) -> f32 { pub fn calculated_top_left_x(&self) -> f32 {
if self.positioning_mode.center_x() { let unclamped_x = if self.positioning_mode.center_x() {
self.reference_x - (self.width / 2.0) self.reference_x - (self.width / 2.0)
} else { } else {
self.reference_x self.reference_x
} };
let max_x = self.output_width - self.width;
unclamped_x.max(0.0).min(max_x)
} }
#[must_use] #[must_use]
pub fn calculated_top_left_y(&self) -> f32 { pub fn calculated_top_left_y(&self) -> f32 {
if self.positioning_mode.center_y() { let unclamped_y = if self.positioning_mode.center_y() {
self.reference_y - (self.height / 2.0) self.reference_y - (self.height / 2.0)
} else { } else {
self.reference_y self.reference_y
} };
let max_y = self.output_height - self.height;
unclamped_y.max(0.0).min(max_y)
} }
} }