diff --git a/.changes/clamp-window-size-dimensions.md b/.changes/clamp-window-size-dimensions.md new file mode 100644 index 000000000000..bb067c2f5c7d --- /dev/null +++ b/.changes/clamp-window-size-dimensions.md @@ -0,0 +1,5 @@ +--- +"tauri-runtime-wry": "patch:bug" +--- + +Fixed the app crashing with a non-unwinding panic during window creation when `width`, `height`, `minWidth`, `minHeight`, `maxWidth` or `maxHeight` was set to a value greater than `i32::MAX` (e.g. on macOS this surfaced as an `NSWindow` frame assertion). These dimensions are now clamped to `i32::MAX` instead of being passed through unchecked. diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index d14f6570ded6..972fccbb2078 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -730,6 +730,13 @@ impl From for ProgressBarStateWrapper { } } +// Values beyond `i32::MAX` have been observed to crash native window creation +// (e.g. an AppKit `NSWindow` frame assertion on macOS), so clamp instead of +// passing them through unchecked. See https://github.com/tauri-apps/tauri/issues/15648 +fn clamp_window_dimension(value: f64) -> f64 { + value.min(i32::MAX as f64) +} + #[derive(Clone, Default)] pub struct WindowBuilderWrapper { inner: TaoWindowBuilder, @@ -880,16 +887,20 @@ impl WindowBuilder for WindowBuilderWrapper { let mut constraints = WindowSizeConstraints::default(); if let Some(min_width) = config.min_width { - constraints.min_width = Some(tao::dpi::LogicalUnit::new(min_width).into()); + constraints.min_width = + Some(tao::dpi::LogicalUnit::new(clamp_window_dimension(min_width)).into()); } if let Some(min_height) = config.min_height { - constraints.min_height = Some(tao::dpi::LogicalUnit::new(min_height).into()); + constraints.min_height = + Some(tao::dpi::LogicalUnit::new(clamp_window_dimension(min_height)).into()); } if let Some(max_width) = config.max_width { - constraints.max_width = Some(tao::dpi::LogicalUnit::new(max_width).into()); + constraints.max_width = + Some(tao::dpi::LogicalUnit::new(clamp_window_dimension(max_width)).into()); } if let Some(max_height) = config.max_height { - constraints.max_height = Some(tao::dpi::LogicalUnit::new(max_height).into()); + constraints.max_height = + Some(tao::dpi::LogicalUnit::new(clamp_window_dimension(max_height)).into()); } if let Some(color) = config.background_color { window = window.background_color(color); @@ -932,21 +943,26 @@ impl WindowBuilder for WindowBuilderWrapper { } fn inner_size(mut self, width: f64, height: f64) -> Self { - self.inner = self.inner.with_inner_size(LogicalSize::new(width, height)); + self.inner = self.inner.with_inner_size(LogicalSize::new( + clamp_window_dimension(width), + clamp_window_dimension(height), + )); self } fn min_inner_size(mut self, min_width: f64, min_height: f64) -> Self { - self.inner = self - .inner - .with_min_inner_size(LogicalSize::new(min_width, min_height)); + self.inner = self.inner.with_min_inner_size(LogicalSize::new( + clamp_window_dimension(min_width), + clamp_window_dimension(min_height), + )); self } fn max_inner_size(mut self, max_width: f64, max_height: f64) -> Self { - self.inner = self - .inner - .with_max_inner_size(LogicalSize::new(max_width, max_height)); + self.inner = self.inner.with_max_inner_size(LogicalSize::new( + clamp_window_dimension(max_width), + clamp_window_dimension(max_height), + )); self }