Skip to content

Commit

Permalink
feat: add granular size constraints APIs (#10242)
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir authored Jul 17, 2024
1 parent 26f2e19 commit da25f73
Show file tree
Hide file tree
Showing 16 changed files with 220 additions and 12 deletions.
7 changes: 7 additions & 0 deletions .changes/split-min-max-constraints-apis-runtime-js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@tauri-apps/api": patch:feat
---

Add APIs to enable setting window size constraints separately:
- Added `WindowSizeConstraints` interface in `window` and `webviewWindow` modules.
- Added `Window.setSizeConstraints` and `WebviewWindow.setSizeConstraints`
8 changes: 8 additions & 0 deletions .changes/split-min-max-constraints-apis-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"tauri": patch:feat
---

Add APIs to enable setting window size constraints separately:
- Added `WindowBuilder::inner_size_constraints` and `WebviewWindowBuilder::inner_size_constraints` which can be used for setting granular constraints.
- Added `WindowSizeConstraints` struct
- Added `Window::set_size_constraints` and `WebviewWindow::set_size_constraints`
6 changes: 6 additions & 0 deletions .changes/split-min-max-constraints-apis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri-runtime": "patch"
"tauri-runtime-wry": "patch"
---

Add `inner_size_constraints` method on `WindowBuilder` trait and `set_size_constraints` method on `WindowDispatch` trait.
6 changes: 6 additions & 0 deletions .changes/split-min-max-constraints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri": "patch:bug"
"@tauri-apps/api": "patch:bug"
---

Apply `minWidth`, `minHieght`, `maxWidth` and `maxHeight` constraints separately, which fixes a long standing bug where these constraints were never applied unless width and height were constrained together.
53 changes: 46 additions & 7 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use tauri_runtime::{
webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler},
window::{
CursorIcon, DetachedWindow, DragDropEvent, PendingWindow, RawWindow, WebviewEvent,
WindowBuilder, WindowBuilderBase, WindowEvent, WindowId,
WindowBuilder, WindowBuilderBase, WindowEvent, WindowId, WindowSizeConstraints,
},
DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
ProgressBarStatus, Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType,
Expand All @@ -43,8 +43,8 @@ use wry::WebViewBuilderExtWindows;
use tao::{
dpi::{
LogicalPosition as TaoLogicalPosition, LogicalSize as TaoLogicalSize,
PhysicalPosition as TaoPhysicalPosition, PhysicalSize as TaoPhysicalSize,
Position as TaoPosition, Size as TaoSize,
LogicalUnit as ToaLogicalUnit, PhysicalPosition as TaoPhysicalPosition,
PhysicalSize as TaoPhysicalSize, Position as TaoPosition, Size as TaoSize,
},
event::{Event, StartCause, WindowEvent as TaoWindowEvent},
event_loop::{
Expand Down Expand Up @@ -774,12 +774,22 @@ impl WindowBuilder for WindowBuilderWrapper {
.minimizable(config.minimizable)
.shadow(config.shadow);

if let (Some(min_width), Some(min_height)) = (config.min_width, config.min_height) {
window = window.min_inner_size(min_width, min_height);
let mut constraints = WindowSizeConstraints::default();

if let Some(min_width) = config.min_width {
constraints.min_width = Some(ToaLogicalUnit::new(min_width).into());
}
if let Some(min_height) = config.min_height {
constraints.min_height = Some(ToaLogicalUnit::new(min_height).into());
}
if let Some(max_width) = config.max_width {
constraints.max_width = Some(ToaLogicalUnit::new(max_width).into());
}
if let (Some(max_width), Some(max_height)) = (config.max_width, config.max_height) {
window = window.max_inner_size(max_width, max_height);
if let Some(max_height) = config.max_height {
constraints.max_height = Some(ToaLogicalUnit::new(max_height).into());
}
window = window.inner_size_constraints(constraints);

if let (Some(x), Some(y)) = (config.x, config.y) {
window = window.position(x, y);
}
Expand Down Expand Up @@ -823,6 +833,16 @@ impl WindowBuilder for WindowBuilderWrapper {
self
}

fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self {
self.inner.window.inner_size_constraints = tao::window::WindowSizeConstraints {
min_width: constraints.min_width,
min_height: constraints.min_height,
max_width: constraints.max_width,
max_height: constraints.max_height,
};
self
}

fn resizable(mut self, resizable: bool) -> Self {
self.inner = self.inner.with_resizable(resizable);
self
Expand Down Expand Up @@ -1144,6 +1164,7 @@ pub enum WindowMessage {
SetSize(Size),
SetMinSize(Option<Size>),
SetMaxSize(Option<Size>),
SetSizeConstraints(WindowSizeConstraints),
SetPosition(Position),
SetFullscreen(bool),
SetFocus,
Expand Down Expand Up @@ -1850,6 +1871,16 @@ impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
)
}

fn set_size_constraints(&self, constraints: WindowSizeConstraints) -> Result<()> {
send_user_message(
&self.context,
Message::Window(
self.window_id,
WindowMessage::SetSizeConstraints(constraints),
),
)
}

fn set_position(&self, position: Position) -> Result<()> {
send_user_message(
&self.context,
Expand Down Expand Up @@ -2831,6 +2862,14 @@ fn handle_user_message<T: UserEvent>(
WindowMessage::SetMaxSize(size) => {
window.set_max_inner_size(size.map(|s| SizeWrapper::from(s).0));
}
WindowMessage::SetSizeConstraints(constraints) => {
window.set_inner_size_constraints(tao::window::WindowSizeConstraints {
min_width: constraints.min_width,
min_height: constraints.min_height,
max_width: constraints.max_width,
max_height: constraints.max_height,
});
}
WindowMessage::SetPosition(position) => {
window.set_outer_position(PositionWrapper::from(position).0)
}
Expand Down
8 changes: 7 additions & 1 deletion core/tauri-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ pub mod window;

use dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use monitor::Monitor;
use window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent};
use window::{
CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent,
WindowSizeConstraints,
};
use window::{WindowBuilder, WindowId};

use http::{
Expand Down Expand Up @@ -735,6 +738,9 @@ pub trait WindowDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 's
/// Updates the window max inner size.
fn set_max_size(&self, size: Option<Size>) -> Result<()>;

/// Sets this window's minimum inner width.
fn set_size_constraints(&self, constraints: WindowSizeConstraints) -> Result<()>;

/// Updates the window position.
fn set_position(&self, position: Position) -> Result<()>;

Expand Down
29 changes: 28 additions & 1 deletion core/tauri-runtime/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use crate::{
Icon, Runtime, UserEvent, WindowDispatch,
};

use serde::{Deserialize, Deserializer};
use dpi::PixelUnit;
use serde::{Deserialize, Deserializer, Serialize};
use tauri_utils::{config::WindowConfig, Theme};
#[cfg(windows)]
use windows::Win32::Foundation::HWND;
Expand Down Expand Up @@ -201,6 +202,28 @@ impl<'de> Deserialize<'de> for CursorIcon {
}
}

/// Window size constraints
#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WindowSizeConstraints {
/// The minimum width a window can be, If this is `None`, the window will have no minimum width.
///
/// The default is `None`.
pub min_width: Option<PixelUnit>,
/// The minimum height a window can be, If this is `None`, the window will have no minimum height.
///
/// The default is `None`.
pub min_height: Option<PixelUnit>,
/// The maximum width a window can be, If this is `None`, the window will have no maximum width.
///
/// The default is `None`.
pub max_width: Option<PixelUnit>,
/// The maximum height a window can be, If this is `None`, the window will have no maximum height.
///
/// The default is `None`.
pub max_height: Option<PixelUnit>,
}

/// Do **NOT** implement this trait except for use in a custom [`Runtime`]
///
/// This trait is separate from [`WindowBuilder`] to prevent "accidental" implementation.
Expand Down Expand Up @@ -237,6 +260,10 @@ pub trait WindowBuilder: WindowBuilderBase {
#[must_use]
fn max_inner_size(self, max_width: f64, max_height: f64) -> Self;

/// Window inner size constraints.
#[must_use]
fn inner_size_constraints(self, constraints: WindowSizeConstraints) -> Self;

/// Whether the window is resizable or not.
/// When resizable is set to false, native window's maximize button is automatically disabled.
#[must_use]
Expand Down
1 change: 1 addition & 0 deletions core/tauri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
("set_content_protected", false),
("set_size", false),
("set_min_size", false),
("set_size_constraints", false),
("set_max_size", false),
("set_position", false),
("set_fullscreen", false),
Expand Down
26 changes: 26 additions & 0 deletions core/tauri/permissions/window/autogenerated/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,32 @@ Denies the set_size command without any pre-configured scope.
<tr>
<td>

`window:allow-set-size-constraints`

</td>
<td>

Enables the set_size_constraints command without any pre-configured scope.

</td>
</tr>

<tr>
<td>

`window:deny-set-size-constraints`

</td>
<td>

Denies the set_size_constraints command without any pre-configured scope.

</td>
</tr>

<tr>
<td>

`window:allow-set-skip-taskbar`

</td>
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.global.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ pub use {
self::runtime::{
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
webview::WebviewAttributes,
window::{CursorIcon, DragDropEvent},
window::{CursorIcon, DragDropEvent, WindowSizeConstraints},
DeviceEventFilter, Rect, UserAttentionType,
},
self::state::{State, StateManager},
Expand Down
14 changes: 14 additions & 0 deletions core/tauri/src/test/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,13 @@ impl WindowBuilder for MockWindowBuilder {
self
}

fn inner_size_constraints(
self,
constraints: tauri_runtime::window::WindowSizeConstraints,
) -> Self {
self
}

fn resizable(self, resizable: bool) -> Self {
self
}
Expand Down Expand Up @@ -937,6 +944,13 @@ impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()> {
Ok(())
}

fn set_size_constraints(
&self,
constraints: tauri_runtime::window::WindowSizeConstraints,
) -> Result<()> {
Ok(())
}
}

#[derive(Debug, Clone)]
Expand Down
13 changes: 13 additions & 0 deletions core/tauri/src/webview/webview_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::{
},
};
use serde::Serialize;
use tauri_runtime::window::WindowSizeConstraints;
use tauri_utils::config::{WebviewUrl, WindowConfig};
use url::Url;

Expand Down Expand Up @@ -406,6 +407,13 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
self
}

/// Window inner size constraints.
#[must_use]
pub fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self {
self.window_builder = self.window_builder.inner_size_constraints(constraints);
self
}

/// Whether the window is resizable or not.
/// When resizable is set to false, native window's maximize button is automatically disabled.
#[must_use]
Expand Down Expand Up @@ -1469,6 +1477,11 @@ impl<R: Runtime> WebviewWindow<R> {
self.webview.window().set_max_size(size.map(|s| s.into()))
}

/// Sets this window's minimum inner width.
pub fn set_size_constraints(&self, constriants: WindowSizeConstraints) -> crate::Result<()> {
self.webview.window().set_size_constraints(constriants)
}

/// Sets this window's position.
pub fn set_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
self.webview.window().set_position(position)
Expand Down
17 changes: 17 additions & 0 deletions core/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub(crate) mod plugin;
use tauri_runtime::{
dpi::{PhysicalPosition, PhysicalSize},
webview::PendingWebview,
window::WindowSizeConstraints,
};
pub use tauri_utils::{config::Color, WindowEffect as Effect, WindowEffectState as EffectState};

Expand Down Expand Up @@ -492,6 +493,13 @@ impl<'a, R: Runtime, M: Manager<R>> WindowBuilder<'a, R, M> {
self
}

/// Window inner size constraints.
#[must_use]
pub fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self {
self.window_builder = self.window_builder.inner_size_constraints(constraints);
self
}

/// Whether the window is resizable or not.
/// When resizable is set to false, native window's maximize button is automatically disabled.
#[must_use]
Expand Down Expand Up @@ -1855,6 +1863,15 @@ tauri::Builder::default()
.map_err(Into::into)
}

/// Sets this window's minimum inner width.
pub fn set_size_constraints(&self, constriants: WindowSizeConstraints) -> crate::Result<()> {
self
.window
.dispatcher
.set_size_constraints(constriants)
.map_err(Into::into)
}

/// Sets this window's position.
pub fn set_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
self
Expand Down
4 changes: 3 additions & 1 deletion core/tauri/src/window/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{

#[cfg(desktop)]
mod desktop_commands {
use tauri_runtime::ResizeDirection;
use tauri_runtime::{window::WindowSizeConstraints, ResizeDirection};
use tauri_utils::TitleBarStyle;

use super::*;
Expand Down Expand Up @@ -132,6 +132,7 @@ mod desktop_commands {
setter!(set_progress_bar, ProgressBarState);
setter!(set_visible_on_all_workspaces, bool);
setter!(set_title_bar_style, TitleBarStyle);
setter!(set_size_constraints, WindowSizeConstraints);

#[command(root = "crate")]
pub async fn set_icon<R: Runtime>(
Expand Down Expand Up @@ -264,6 +265,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
desktop_commands::set_size,
desktop_commands::set_min_size,
desktop_commands::set_max_size,
desktop_commands::set_size_constraints,
desktop_commands::set_position,
desktop_commands::set_fullscreen,
desktop_commands::set_focus,
Expand Down
Loading

0 comments on commit da25f73

Please sign in to comment.