浏览代码

feat(core): Ability to disable minimize/maximize/close native window's buttons, closes #2353 (#6665)

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Tomáš Diblík 2 年之前
父节点
当前提交
c4d6fb4b1e

+ 5 - 0
.changes/disable-window-controls-api-options.md

@@ -0,0 +1,5 @@
+---
+'@tauri-apps/api': 'minor:feat'
+---
+
+Added the `maximizable`, `minimizable` and `closable` fields on `WindowOptions`.

+ 5 - 0
.changes/disable-window-controls-api.md

@@ -0,0 +1,5 @@
+---
+'@tauri-apps/api': 'minor:feat'
+---
+
+Added the `setMaximizable`, `setMinimizable`, `setClosable`, `isMaximizable`, `isMinimizable` and `isClosable` methods.

+ 5 - 0
.changes/disable-window-controls-config.md

@@ -0,0 +1,5 @@
+---
+'tauri-utils': 'minor:feat'
+---
+
+Added the `maximizable`, `minimizable` and `closable` options to the window configuration.

+ 6 - 0
.changes/disable-window-controls-runtime-builder.md

@@ -0,0 +1,6 @@
+---
+'tauri-runtime-wry': 'minor:feat'
+'tauri-runtime': 'minor:feat'
+---
+
+Added the `maximizable`, `minimizable` and `closable` methods to `WindowBuilder`.

+ 6 - 0
.changes/disable-window-controls-runtime-window.md

@@ -0,0 +1,6 @@
+---
+'tauri-runtime-wry': 'minor:feat'
+'tauri-runtime': 'minor:feat'
+---
+
+Added `set_maximizable`, `set_minimizable`, `set_closable`, `is_maximizable`, `is_minimizable` and `is_closable` methods to the `Dispatch` trait.

+ 5 - 0
.changes/disable-window-controls-window-builder.md

@@ -0,0 +1,5 @@
+---
+'tauri': 'minor:feat'
+---
+
+Added the `maximizable`, `minimizable` and `closable` options to the window builder.

+ 5 - 0
.changes/disable-window-controls-window.md

@@ -0,0 +1,5 @@
+---
+'tauri': 'minor:feat'
+---
+
+Added the `set_maximizable`, `set_minimizable`, `set_closable`, `is_maximizable`, `is_minimizable` and `is_closable` methods on `Window`.

+ 40 - 1
core/tauri-config-schema/schema.json

@@ -105,6 +105,7 @@
             "print": false,
             "requestUserAttention": false,
             "setAlwaysOnTop": false,
+            "setClosable": false,
             "setContentProtected": false,
             "setCursorGrab": false,
             "setCursorIcon": false,
@@ -116,7 +117,9 @@
             "setIcon": false,
             "setIgnoreCursorEvents": false,
             "setMaxSize": false,
+            "setMaximizable": false,
             "setMinSize": false,
+            "setMinimizable": false,
             "setPosition": false,
             "setResizable": false,
             "setSize": false,
@@ -383,6 +386,7 @@
               "print": false,
               "requestUserAttention": false,
               "setAlwaysOnTop": false,
+              "setClosable": false,
               "setContentProtected": false,
               "setCursorGrab": false,
               "setCursorIcon": false,
@@ -394,7 +398,9 @@
               "setIcon": false,
               "setIgnoreCursorEvents": false,
               "setMaxSize": false,
+              "setMaximizable": false,
               "setMinSize": false,
+              "setMinimizable": false,
               "setPosition": false,
               "setResizable": false,
               "setSize": false,
@@ -605,7 +611,22 @@
           "format": "double"
         },
         "resizable": {
-          "description": "Whether the window is resizable or not.",
+          "description": "Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.",
+          "default": true,
+          "type": "boolean"
+        },
+        "maximizable": {
+          "description": "Whether the window's native maximize button is enabled or not. If resizable is set to false, this setting is ignored.\n\n## Platform-specific\n\n- **macOS:** Disables the \"zoom\" button in the window titlebar, which is also used to enter fullscreen mode. - **Linux / iOS / Android:** Unsupported.",
+          "default": true,
+          "type": "boolean"
+        },
+        "minimizable": {
+          "description": "Whether the window's native minimize button is enabled or not.\n\n## Platform-specific\n\n- **Linux / iOS / Android:** Unsupported.",
+          "default": true,
+          "type": "boolean"
+        },
+        "closable": {
+          "description": "Whether the window's native close button is enabled or not.\n\n## Platform-specific\n\n- **Linux:** \"GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible\" - **iOS / Android:** Unsupported.",
           "default": true,
           "type": "boolean"
         },
@@ -1809,6 +1830,7 @@
             "print": false,
             "requestUserAttention": false,
             "setAlwaysOnTop": false,
+            "setClosable": false,
             "setContentProtected": false,
             "setCursorGrab": false,
             "setCursorIcon": false,
@@ -1820,7 +1842,9 @@
             "setIcon": false,
             "setIgnoreCursorEvents": false,
             "setMaxSize": false,
+            "setMaximizable": false,
             "setMinSize": false,
+            "setMinimizable": false,
             "setPosition": false,
             "setResizable": false,
             "setSize": false,
@@ -2117,6 +2141,21 @@
           "default": false,
           "type": "boolean"
         },
+        "setMaximizable": {
+          "description": "Allows setting whether the window's native maximize button is enabled or not.",
+          "default": false,
+          "type": "boolean"
+        },
+        "setMinimizable": {
+          "description": "Allows setting whether the window's native minimize button is enabled or not.",
+          "default": false,
+          "type": "boolean"
+        },
+        "setClosable": {
+          "description": "Allows setting whether the window's native close button is enabled or not.",
+          "default": false,
+          "type": "boolean"
+        },
         "setTitle": {
           "description": "Allows changing the window title.",
           "default": false,

+ 66 - 0
core/tauri-runtime-wry/src/lib.rs

@@ -717,6 +717,9 @@ impl WindowBuilder for WindowBuilderWrapper {
       .inner_size(config.width, config.height)
       .visible(config.visible)
       .resizable(config.resizable)
+      .maximizable(config.maximizable)
+      .minimizable(config.minimizable)
+      .closable(config.closable)
       .fullscreen(config.fullscreen)
       .decorations(config.decorations)
       .maximized(config.maximized)
@@ -815,6 +818,21 @@ impl WindowBuilder for WindowBuilderWrapper {
     self
   }
 
+  fn maximizable(mut self, maximizable: bool) -> Self {
+    self.inner = self.inner.with_maximizable(maximizable);
+    self
+  }
+
+  fn minimizable(mut self, minimizable: bool) -> Self {
+    self.inner = self.inner.with_minimizable(minimizable);
+    self
+  }
+
+  fn closable(mut self, closable: bool) -> Self {
+    self.inner = self.inner.with_closable(closable);
+    self
+  }
+
   fn title<S: Into<String>>(mut self, title: S) -> Self {
     self.inner = self.inner.with_title(title.into());
     self
@@ -1056,6 +1074,9 @@ pub enum WindowMessage {
   IsMaximized(Sender<bool>),
   IsDecorated(Sender<bool>),
   IsResizable(Sender<bool>),
+  IsMaximizable(Sender<bool>),
+  IsMinimizable(Sender<bool>),
+  IsClosable(Sender<bool>),
   IsVisible(Sender<bool>),
   Title(Sender<String>),
   IsMenuVisible(Sender<bool>),
@@ -1076,6 +1097,9 @@ pub enum WindowMessage {
   Center,
   RequestUserAttention(Option<UserAttentionTypeWrapper>),
   SetResizable(bool),
+  SetMaximizable(bool),
+  SetMinimizable(bool),
+  SetClosable(bool),
   SetTitle(String),
   Maximize,
   Unmaximize,
@@ -1294,6 +1318,21 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
     window_getter!(self, WindowMessage::IsResizable)
   }
 
+  /// Gets the current native window's maximize button state
+  fn is_maximizable(&self) -> Result<bool> {
+    window_getter!(self, WindowMessage::IsMaximizable)
+  }
+
+  /// Gets the current native window's minimize button state
+  fn is_minimizable(&self) -> Result<bool> {
+    window_getter!(self, WindowMessage::IsMinimizable)
+  }
+
+  /// Gets the current native window's close button state
+  fn is_closable(&self) -> Result<bool> {
+    window_getter!(self, WindowMessage::IsClosable)
+  }
+
   fn is_visible(&self) -> Result<bool> {
     window_getter!(self, WindowMessage::IsVisible)
   }
@@ -1385,6 +1424,27 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
     )
   }
 
+  fn set_maximizable(&self, maximizable: bool) -> Result<()> {
+    send_user_message(
+      &self.context,
+      Message::Window(self.window_id, WindowMessage::SetMaximizable(maximizable)),
+    )
+  }
+
+  fn set_minimizable(&self, minimizable: bool) -> Result<()> {
+    send_user_message(
+      &self.context,
+      Message::Window(self.window_id, WindowMessage::SetMinimizable(minimizable)),
+    )
+  }
+
+  fn set_closable(&self, closable: bool) -> Result<()> {
+    send_user_message(
+      &self.context,
+      Message::Window(self.window_id, WindowMessage::SetClosable(closable)),
+    )
+  }
+
   fn set_title<S: Into<String>>(&self, title: S) -> Result<()> {
     send_user_message(
       &self.context,
@@ -2409,6 +2469,9 @@ fn handle_user_message<T: UserEvent>(
             WindowMessage::IsMaximized(tx) => tx.send(window.is_maximized()).unwrap(),
             WindowMessage::IsDecorated(tx) => tx.send(window.is_decorated()).unwrap(),
             WindowMessage::IsResizable(tx) => tx.send(window.is_resizable()).unwrap(),
+            WindowMessage::IsMaximizable(tx) => tx.send(window.is_maximizable()).unwrap(),
+            WindowMessage::IsMinimizable(tx) => tx.send(window.is_minimizable()).unwrap(),
+            WindowMessage::IsClosable(tx) => tx.send(window.is_closable()).unwrap(),
             WindowMessage::IsVisible(tx) => tx.send(window.is_visible()).unwrap(),
             WindowMessage::Title(tx) => tx.send(window.title()).unwrap(),
             WindowMessage::IsMenuVisible(tx) => tx.send(window.is_menu_visible()).unwrap(),
@@ -2441,6 +2504,9 @@ fn handle_user_message<T: UserEvent>(
               window.request_user_attention(request_type.map(|r| r.0));
             }
             WindowMessage::SetResizable(resizable) => window.set_resizable(resizable),
+            WindowMessage::SetMaximizable(maximizable) => window.set_maximizable(maximizable),
+            WindowMessage::SetMinimizable(minimizable) => window.set_minimizable(minimizable),
+            WindowMessage::SetClosable(closable) => window.set_closable(closable),
             WindowMessage::SetTitle(title) => window.set_title(&title),
             WindowMessage::Maximize => window.set_maximized(true),
             WindowMessage::Unmaximize => window.set_maximized(false),

+ 45 - 0
core/tauri-runtime/src/lib.rs

@@ -582,6 +582,27 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
   /// Gets the window’s current resizable state.
   fn is_resizable(&self) -> Result<bool>;
 
+  /// Gets the window's native maximize button state.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  fn is_maximizable(&self) -> Result<bool>;
+
+  /// Gets the window's native minize button state.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  fn is_minimizable(&self) -> Result<bool>;
+
+  /// Gets the window's native close button state.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **iOS / Android:** Unsupported.
+  fn is_closable(&self) -> Result<bool>;
+
   /// Gets the window's current visibility state.
   fn is_visible(&self) -> Result<bool>;
   /// Gets the window's current title.
@@ -640,6 +661,30 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
   /// Updates the window resizable flag.
   fn set_resizable(&self, resizable: bool) -> Result<()>;
 
+  /// Updates the window's native maximize button state.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
+  /// - **Linux / iOS / Android:** Unsupported.
+  fn set_maximizable(&self, maximizable: bool) -> Result<()>;
+
+  /// Updates the window's native minimize button state.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  fn set_minimizable(&self, minimizable: bool) -> Result<()>;
+
+  /// Updates the window's native close button state.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
+  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
+  /// - **iOS / Android:** Unsupported.
+  fn set_closable(&self, closable: bool) -> Result<()>;
+
   /// Updates the window title.
   fn set_title<S: Into<String>>(&self, title: S) -> Result<()>;
 

+ 29 - 0
core/tauri-runtime/src/webview.rs

@@ -157,9 +157,38 @@ pub trait WindowBuilder: WindowBuilderBase {
   fn max_inner_size(self, max_width: f64, max_height: f64) -> Self;
 
   /// Whether the window is resizable or not.
+  /// When resizable is set to false, native window's maximize button is automatically disabled.
   #[must_use]
   fn resizable(self, resizable: bool) -> Self;
 
+  /// Whether the window's native maximize button is enabled or not.
+  /// If resizable is set to false, this setting is ignored.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
+  /// - **Linux / iOS / Android:** Unsupported.
+  #[must_use]
+  fn maximizable(self, maximizable: bool) -> Self;
+
+  /// Whether the window's native minimize button is enabled or not.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  #[must_use]
+  fn minimizable(self, minimizable: bool) -> Self;
+
+  /// Whether the window's native close button is enabled or not.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
+  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
+  /// - **iOS / Android:** Unsupported.
+  #[must_use]
+  fn closable(self, closable: bool) -> Self;
+
   /// The title of the window in the title bar.
   #[must_use]
   fn title<S: Into<String>>(self, title: S) -> Self;

+ 50 - 1
core/tauri-utils/src/config.rs

@@ -926,9 +926,34 @@ pub struct WindowConfig {
   /// The max window height.
   #[serde(alias = "max-height")]
   pub max_height: Option<f64>,
-  /// Whether the window is resizable or not.
+  /// Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.
   #[serde(default = "default_true")]
   pub resizable: bool,
+  /// Whether the window's native maximize button is enabled or not.
+  /// If resizable is set to false, this setting is ignored.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
+  /// - **Linux / iOS / Android:** Unsupported.
+  #[serde(default = "default_true")]
+  pub maximizable: bool,
+  /// Whether the window's native minimize button is enabled or not.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  #[serde(default = "default_true")]
+  pub minimizable: bool,
+  /// Whether the window's native close button is enabled or not.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
+  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
+  /// - **iOS / Android:** Unsupported.
+  #[serde(default = "default_true")]
+  pub closable: bool,
   /// The window title.
   #[serde(default = "default_title")]
   pub title: String,
@@ -1004,6 +1029,9 @@ impl Default for WindowConfig {
       max_width: None,
       max_height: None,
       resizable: true,
+      maximizable: true,
+      minimizable: true,
+      closable: true,
       title: default_title(),
       fullscreen: false,
       focus: false,
@@ -1435,6 +1463,15 @@ pub struct WindowAllowlistConfig {
   /// Allows setting the resizable flag of the window.
   #[serde(default, alias = "set-resizable")]
   pub set_resizable: bool,
+  /// Allows setting whether the window's native maximize button is enabled or not.
+  #[serde(default, alias = "set-maximizable")]
+  pub set_maximizable: bool,
+  /// Allows setting whether the window's native minimize button is enabled or not.
+  #[serde(default, alias = "set-minimizable")]
+  pub set_minimizable: bool,
+  /// Allows setting whether the window's native close button is enabled or not.
+  #[serde(default, alias = "set-closable")]
+  pub set_closable: bool,
   /// Allows changing the window title.
   #[serde(default, alias = "set-title")]
   pub set_title: bool,
@@ -1523,6 +1560,9 @@ impl Allowlist for WindowAllowlistConfig {
       center: true,
       request_user_attention: true,
       set_resizable: true,
+      set_maximizable: true,
+      set_minimizable: true,
+      set_closable: true,
       set_title: true,
       maximize: true,
       unmaximize: true,
@@ -1569,6 +1609,9 @@ impl Allowlist for WindowAllowlistConfig {
         "window-request-user-attention"
       );
       check_feature!(self, features, set_resizable, "window-set-resizable");
+      check_feature!(self, features, set_maximizable, "window-set-maximizable");
+      check_feature!(self, features, set_minimizable, "window-set-minimizable");
+      check_feature!(self, features, set_closable, "window-set-closable");
       check_feature!(self, features, set_title, "window-set-title");
       check_feature!(self, features, maximize, "window-maximize");
       check_feature!(self, features, unmaximize, "window-unmaximize");
@@ -3222,6 +3265,9 @@ mod build {
       let max_width = opt_lit(self.max_width.as_ref());
       let max_height = opt_lit(self.max_height.as_ref());
       let resizable = self.resizable;
+      let maximizable = self.maximizable;
+      let minimizable = self.minimizable;
+      let closable = self.closable;
       let title = str_lit(&self.title);
       let fullscreen = self.fullscreen;
       let focus = self.focus;
@@ -3256,6 +3302,9 @@ mod build {
         max_width,
         max_height,
         resizable,
+        maximizable,
+        minimizable,
+        closable,
         title,
         fullscreen,
         focus,

+ 6 - 0
core/tauri/Cargo.toml

@@ -232,6 +232,9 @@ window-all = [
   "window-center",
   "window-request-user-attention",
   "window-set-resizable",
+  "window-set-maximizable",
+  "window-set-minimizable",
+  "window-set-closable",
   "window-set-title",
   "window-maximize",
   "window-unmaximize",
@@ -263,6 +266,9 @@ window-create = [ ]
 window-center = [ ]
 window-request-user-attention = [ ]
 window-set-resizable = [ ]
+window-set-maximizable = [ ]
+window-set-minimizable = [ ]
+window-set-closable = [ ]
 window-set-title = [ ]
 window-maximize = [ ]
 window-unmaximize = [ ]

+ 3 - 0
core/tauri/build.rs

@@ -71,6 +71,9 @@ fn main() {
       "center",
       "request-user-attention",
       "set-resizable",
+      "set-maximizable",
+      "set-minimizable",
+      "set-closable",
       "set-title",
       "maximize",
       "unmaximize",

文件差异内容过多而无法显示
+ 0 - 0
core/tauri/scripts/bundle.global.js


+ 18 - 0
core/tauri/src/endpoints/window.rs

@@ -67,6 +67,9 @@ pub enum WindowManagerCmd {
   IsMaximized,
   IsDecorated,
   IsResizable,
+  IsMaximizable,
+  IsMinimizable,
+  IsClosable,
   IsVisible,
   Title,
   CurrentMonitor,
@@ -80,6 +83,12 @@ pub enum WindowManagerCmd {
   RequestUserAttention(Option<UserAttentionType>),
   #[cfg(window_set_resizable)]
   SetResizable(bool),
+  #[cfg(window_set_maximizable)]
+  SetMaximizable(bool),
+  #[cfg(window_set_minimizable)]
+  SetMinimizable(bool),
+  #[cfg(window_set_closable)]
+  SetClosable(bool),
   #[cfg(window_set_title)]
   SetTitle(String),
   #[cfg(window_maximize)]
@@ -256,6 +265,9 @@ impl Cmd {
       WindowManagerCmd::IsMaximized => return Ok(window.is_maximized()?.into()),
       WindowManagerCmd::IsDecorated => return Ok(window.is_decorated()?.into()),
       WindowManagerCmd::IsResizable => return Ok(window.is_resizable()?.into()),
+      WindowManagerCmd::IsMaximizable => return Ok(window.is_maximizable()?.into()),
+      WindowManagerCmd::IsMinimizable => return Ok(window.is_minimizable()?.into()),
+      WindowManagerCmd::IsClosable => return Ok(window.is_closable()?.into()),
       WindowManagerCmd::IsVisible => return Ok(window.is_visible()?.into()),
       WindowManagerCmd::Title => return Ok(window.title()?.into()),
       WindowManagerCmd::CurrentMonitor => return Ok(window.current_monitor()?.into()),
@@ -271,6 +283,12 @@ impl Cmd {
       }
       #[cfg(window_set_resizable)]
       WindowManagerCmd::SetResizable(resizable) => window.set_resizable(resizable)?,
+      #[cfg(window_set_maximizable)]
+      WindowManagerCmd::SetMaximizable(maximizable) => window.set_maximizable(maximizable)?,
+      #[cfg(window_set_minimizable)]
+      WindowManagerCmd::SetMinimizable(minimizable) => window.set_minimizable(minimizable)?,
+      #[cfg(window_set_closable)]
+      WindowManagerCmd::SetClosable(closable) => window.set_closable(closable)?,
       #[cfg(window_set_title)]
       WindowManagerCmd::SetTitle(title) => window.set_title(&title)?,
       #[cfg(window_maximize)]

+ 3 - 0
core/tauri/src/lib.rs

@@ -125,6 +125,9 @@
 //! - **window-center**: Enables the [`center` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#center).
 //! - **window-request-user-attention**: Enables the [`requestUserAttention` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#requestuserattention).
 //! - **window-set-resizable**: Enables the [`setResizable` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setresizable).
+//! - **window-set-maximizable**: Enables the [`setMaximizable` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setmaximizable).
+//! - **window-set-minimizable**: Enables the [`setMinimizable` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setminimizable).
+//! - **window-set-closable**: Enables the [`setClosable` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#setclosable).
 //! - **window-set-title**: Enables the [`setTitle` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#settitle).
 //! - **window-maximize**: Enables the [`maximize` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#maximize).
 //! - **window-unmaximize**: Enables the [`unmaximize` API](https://tauri.app/en/docs/api/js/classes/window.WebviewWindow#unmaximize).

+ 36 - 0
core/tauri/src/test/mock_runtime.rs

@@ -221,6 +221,18 @@ impl WindowBuilder for MockWindowBuilder {
     self
   }
 
+  fn maximizable(self, resizable: bool) -> Self {
+    self
+  }
+
+  fn minimizable(self, resizable: bool) -> Self {
+    self
+  }
+
+  fn closable(self, resizable: bool) -> Self {
+    self
+  }
+
   fn title<S: Into<String>>(self, title: S) -> Self {
     self
   }
@@ -391,6 +403,18 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
     Ok(false)
   }
 
+  fn is_maximizable(&self) -> Result<bool> {
+    Ok(true)
+  }
+
+  fn is_minimizable(&self) -> Result<bool> {
+    Ok(true)
+  }
+
+  fn is_closable(&self) -> Result<bool> {
+    Ok(true)
+  }
+
   fn is_visible(&self) -> Result<bool> {
     Ok(true)
   }
@@ -457,6 +481,18 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
     Ok(())
   }
 
+  fn set_maximizable(&self, maximizable: bool) -> Result<()> {
+    Ok(())
+  }
+
+  fn set_minimizable(&self, minimizable: bool) -> Result<()> {
+    Ok(())
+  }
+
+  fn set_closable(&self, closable: bool) -> Result<()> {
+    Ok(())
+  }
+
   fn set_title<S: Into<String>>(&self, title: S) -> Result<()> {
     Ok(())
   }

+ 109 - 0
core/tauri/src/window.rs

@@ -384,12 +384,50 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
   }
 
   /// Whether the window is resizable or not.
+  /// When resizable is set to false, native window's maximize button is automatically disabled.
   #[must_use]
   pub fn resizable(mut self, resizable: bool) -> Self {
     self.window_builder = self.window_builder.resizable(resizable);
     self
   }
 
+  /// Whether the window's native maximize button is enabled or not.
+  /// If resizable is set to false, this setting is ignored.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
+  /// - **Linux / iOS / Android:** Unsupported.
+  #[must_use]
+  pub fn maximizable(mut self, maximizable: bool) -> Self {
+    self.window_builder = self.window_builder.maximizable(maximizable);
+    self
+  }
+
+  /// Whether the window's native minimize button is enabled or not.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  #[must_use]
+  pub fn minimizable(mut self, minimizable: bool) -> Self {
+    self.window_builder = self.window_builder.minimizable(minimizable);
+    self
+  }
+
+  /// Whether the window's native close button is enabled or not.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
+  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
+  /// - **iOS / Android:** Unsupported.
+  #[must_use]
+  pub fn closable(mut self, closable: bool) -> Self {
+    self.window_builder = self.window_builder.closable(closable);
+    self
+  }
+
   /// The title of the window in the title bar.
   #[must_use]
   pub fn title<S: Into<String>>(mut self, title: S) -> Self {
@@ -1014,6 +1052,33 @@ impl<R: Runtime> Window<R> {
     self.window.dispatcher.is_resizable().map_err(Into::into)
   }
 
+  /// Gets the window’s native maximize button state
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  pub fn is_maximizable(&self) -> crate::Result<bool> {
+    self.window.dispatcher.is_maximizable().map_err(Into::into)
+  }
+
+  /// Gets the window’s native minimize button state
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  pub fn is_minimizable(&self) -> crate::Result<bool> {
+    self.window.dispatcher.is_minimizable().map_err(Into::into)
+  }
+
+  /// Gets the window’s native close button state
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  pub fn is_closable(&self) -> crate::Result<bool> {
+    self.window.dispatcher.is_closable().map_err(Into::into)
+  }
+
   /// Gets the window's current visibility state.
   pub fn is_visible(&self) -> crate::Result<bool> {
     self.window.dispatcher.is_visible().map_err(Into::into)
@@ -1153,6 +1218,7 @@ impl<R: Runtime> Window<R> {
   }
 
   /// Determines if this window should be resizable.
+  /// When resizable is set to false, native window's maximize button is automatically disabled.
   pub fn set_resizable(&self, resizable: bool) -> crate::Result<()> {
     self
       .window
@@ -1161,6 +1227,49 @@ impl<R: Runtime> Window<R> {
       .map_err(Into::into)
   }
 
+  /// Determines if this window's native maximize button should be enabled.
+  /// If resizable is set to false, this setting is ignored.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
+  /// - **Linux / iOS / Android:** Unsupported.
+  pub fn set_maximizable(&self, maximizable: bool) -> crate::Result<()> {
+    self
+      .window
+      .dispatcher
+      .set_maximizable(maximizable)
+      .map_err(Into::into)
+  }
+
+  /// Determines if this window's native minize button should be enabled.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux / iOS / Android:** Unsupported.
+  pub fn set_minimizable(&self, minimizable: bool) -> crate::Result<()> {
+    self
+      .window
+      .dispatcher
+      .set_minimizable(minimizable)
+      .map_err(Into::into)
+  }
+
+  /// Determines if this window's native close button should be enabled.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
+  ///   Depending on the system, this function may not have any effect when called on a window that is already visible"
+  /// - **iOS / Android:** Unsupported.
+  pub fn set_closable(&self, closable: bool) -> crate::Result<()> {
+    self
+      .window
+      .dispatcher
+      .set_closable(closable)
+      .map_err(Into::into)
+  }
+
   /// Set this window's title.
   pub fn set_title(&self, title: &str) -> crate::Result<()> {
     self

文件差异内容过多而无法显示
+ 0 - 0
examples/api/dist/assets/index.css


文件差异内容过多而无法显示
+ 0 - 0
examples/api/dist/assets/index.js


+ 18 - 0
examples/api/src/views/Window.svelte

@@ -63,6 +63,9 @@
 
   let urlValue = 'https://tauri.app'
   let resizable = true
+  let maximizable = true
+  let minimizable = true
+  let closable = true
   let maximized = false
   let decorations = true
   let alwaysOnTop = false
@@ -178,6 +181,9 @@
     loadWindowSize()
   }
   $: windowMap[selectedWindow]?.setResizable(resizable)
+  $: windowMap[selectedWindow]?.setMaximizable(maximizable)
+  $: windowMap[selectedWindow]?.setMinimizable(minimizable)
+  $: windowMap[selectedWindow]?.setClosable(closable)
   $: maximized
     ? windowMap[selectedWindow]?.maximize()
     : windowMap[selectedWindow]?.unmaximize()
@@ -280,6 +286,18 @@
         Resizable
         <input type="checkbox" bind:checked={resizable} />
       </label>
+      <label>
+        Maximizable
+        <input type="checkbox" bind:checked={maximizable} />
+      </label>
+      <label>
+        Minimizable
+        <input type="checkbox" bind:checked={minimizable} />
+      </label>
+      <label>
+        Closable
+        <input type="checkbox" bind:checked={closable} />
+      </label>
       <label>
         Has decorations
         <input type="checkbox" bind:checked={decorations} />

文件差异内容过多而无法显示
+ 0 - 0
tooling/api/docs/js-api.json


+ 193 - 2
tooling/api/src/window.ts

@@ -18,6 +18,9 @@
  *         "center": true,
  *         "requestUserAttention": true,
  *         "setResizable": true,
+ *         "setMaximizable": true,
+ *         "setMinimizable": true,
+ *         "setClosable": true,
  *         "setTitle": true,
  *         "maximize": true,
  *         "unmaximize": true,
@@ -683,6 +686,96 @@ class WindowManager extends WebviewWindowHandle {
     })
   }
 
+  /**
+   * Gets the window’s native maximize button state.
+   *
+   * #### Platform-specific
+   *
+   * - **Linux / iOS / Android:** Unsupported.
+   *
+   * @example
+   * ```typescript
+   * import { appWindow } from '@tauri-apps/api/window';
+   * const maximizable = await appWindow.isMaximizable();
+   * ```
+   *
+   * @returns Whether the window's native maximize button is enabled or not.
+   *  */
+  async isMaximizable(): Promise<boolean> {
+    return invokeTauriCommand({
+      __tauriModule: 'Window',
+      message: {
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isMaximizable'
+          }
+        }
+      }
+    })
+  }
+
+  /**
+   * Gets the window’s native minimize button state.
+   *
+   * #### Platform-specific
+   *
+   * - **Linux / iOS / Android:** Unsupported.
+   *
+   * @example
+   * ```typescript
+   * import { appWindow } from '@tauri-apps/api/window';
+   * const minimizable = await appWindow.isMinimizable();
+   * ```
+   *
+   * @returns Whether the window's native minimize button is enabled or not.
+   *  */
+  async isMinimizable(): Promise<boolean> {
+    return invokeTauriCommand({
+      __tauriModule: 'Window',
+      message: {
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isMinimizable'
+          }
+        }
+      }
+    })
+  }
+
+  /**
+   * Gets the window’s native close button state.
+   *
+   * #### Platform-specific
+   *
+   * - **Linux / iOS / Android:** Unsupported.
+   *
+   * @example
+   * ```typescript
+   * import { appWindow } from '@tauri-apps/api/window';
+   * const closable = await appWindow.isClosable();
+   * ```
+   *
+   * @returns Whether the window's native close button is enabled or not.
+   *  */
+  async isClosable(): Promise<boolean> {
+    return invokeTauriCommand({
+      __tauriModule: 'Window',
+      message: {
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isClosable'
+          }
+        }
+      }
+    })
+  }
+
   /**
    * Gets the window's current visible state.
    * @example
@@ -773,7 +866,6 @@ class WindowManager extends WebviewWindowHandle {
    * await appWindow.center();
    * ```
    *
-   * @param resizable
    * @returns A promise indicating the success or failure of the operation.
    */
   async center(): Promise<void> {
@@ -809,7 +901,7 @@ class WindowManager extends WebviewWindowHandle {
    * await appWindow.requestUserAttention();
    * ```
    *
-   * @param resizable
+   * @param requestType
    * @returns A promise indicating the success or failure of the operation.
    */
   async requestUserAttention(
@@ -865,6 +957,105 @@ class WindowManager extends WebviewWindowHandle {
     })
   }
 
+  /**
+   * Sets whether the window's native maximize button is enabled or not.
+   * If resizable is set to false, this setting is ignored.
+   *
+   * #### Platform-specific
+   *
+   * - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
+   * - **Linux / iOS / Android:** Unsupported.
+   *
+   * @example
+   * ```typescript
+   * import { appWindow } from '@tauri-apps/api/window';
+   * await appWindow.setMaximizable(false);
+   * ```
+   *
+   * @param maximizable
+   * @returns A promise indicating the success or failure of the operation.
+   */
+  async setMaximizable(maximizable: boolean): Promise<void> {
+    return invokeTauriCommand({
+      __tauriModule: 'Window',
+      message: {
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setMaximizable',
+            payload: maximizable
+          }
+        }
+      }
+    })
+  }
+
+  /**
+   * Sets whether the window's native minimize button is enabled or not.
+   *
+   * #### Platform-specific
+   *
+   * - **Linux / iOS / Android:** Unsupported.
+   *
+   * @example
+   * ```typescript
+   * import { appWindow } from '@tauri-apps/api/window';
+   * await appWindow.setMinimizable(false);
+   * ```
+   *
+   * @param minimizable
+   * @returns A promise indicating the success or failure of the operation.
+   */
+  async setMinimizable(minimizable: boolean): Promise<void> {
+    return invokeTauriCommand({
+      __tauriModule: 'Window',
+      message: {
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setMinimizable',
+            payload: minimizable
+          }
+        }
+      }
+    })
+  }
+
+  /**
+   * Sets whether the window's native close button is enabled or not.
+   *
+   * #### Platform-specific
+   *
+   * - **Linux:** GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible
+   * - **iOS / Android:** Unsupported.
+   *
+   * @example
+   * ```typescript
+   * import { appWindow } from '@tauri-apps/api/window';
+   * await appWindow.setClosable(false);
+   * ```
+   *
+   * @param closable
+   * @returns A promise indicating the success or failure of the operation.
+   */
+  async setClosable(closable: boolean): Promise<void> {
+    return invokeTauriCommand({
+      __tauriModule: 'Window',
+      message: {
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setClosable',
+            payload: closable
+          }
+        }
+      }
+    })
+  }
+
   /**
    * Sets the window title.
    * @example

+ 40 - 1
tooling/cli/schema.json

@@ -105,6 +105,7 @@
             "print": false,
             "requestUserAttention": false,
             "setAlwaysOnTop": false,
+            "setClosable": false,
             "setContentProtected": false,
             "setCursorGrab": false,
             "setCursorIcon": false,
@@ -116,7 +117,9 @@
             "setIcon": false,
             "setIgnoreCursorEvents": false,
             "setMaxSize": false,
+            "setMaximizable": false,
             "setMinSize": false,
+            "setMinimizable": false,
             "setPosition": false,
             "setResizable": false,
             "setSize": false,
@@ -383,6 +386,7 @@
               "print": false,
               "requestUserAttention": false,
               "setAlwaysOnTop": false,
+              "setClosable": false,
               "setContentProtected": false,
               "setCursorGrab": false,
               "setCursorIcon": false,
@@ -394,7 +398,9 @@
               "setIcon": false,
               "setIgnoreCursorEvents": false,
               "setMaxSize": false,
+              "setMaximizable": false,
               "setMinSize": false,
+              "setMinimizable": false,
               "setPosition": false,
               "setResizable": false,
               "setSize": false,
@@ -605,7 +611,22 @@
           "format": "double"
         },
         "resizable": {
-          "description": "Whether the window is resizable or not.",
+          "description": "Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.",
+          "default": true,
+          "type": "boolean"
+        },
+        "maximizable": {
+          "description": "Whether the window's native maximize button is enabled or not. If resizable is set to false, this setting is ignored.\n\n## Platform-specific\n\n- **macOS:** Disables the \"zoom\" button in the window titlebar, which is also used to enter fullscreen mode. - **Linux / iOS / Android:** Unsupported.",
+          "default": true,
+          "type": "boolean"
+        },
+        "minimizable": {
+          "description": "Whether the window's native minimize button is enabled or not.\n\n## Platform-specific\n\n- **Linux / iOS / Android:** Unsupported.",
+          "default": true,
+          "type": "boolean"
+        },
+        "closable": {
+          "description": "Whether the window's native close button is enabled or not.\n\n## Platform-specific\n\n- **Linux:** \"GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible\" - **iOS / Android:** Unsupported.",
           "default": true,
           "type": "boolean"
         },
@@ -1809,6 +1830,7 @@
             "print": false,
             "requestUserAttention": false,
             "setAlwaysOnTop": false,
+            "setClosable": false,
             "setContentProtected": false,
             "setCursorGrab": false,
             "setCursorIcon": false,
@@ -1820,7 +1842,9 @@
             "setIcon": false,
             "setIgnoreCursorEvents": false,
             "setMaxSize": false,
+            "setMaximizable": false,
             "setMinSize": false,
+            "setMinimizable": false,
             "setPosition": false,
             "setResizable": false,
             "setSize": false,
@@ -2117,6 +2141,21 @@
           "default": false,
           "type": "boolean"
         },
+        "setMaximizable": {
+          "description": "Allows setting whether the window's native maximize button is enabled or not.",
+          "default": false,
+          "type": "boolean"
+        },
+        "setMinimizable": {
+          "description": "Allows setting whether the window's native minimize button is enabled or not.",
+          "default": false,
+          "type": "boolean"
+        },
+        "setClosable": {
+          "description": "Allows setting whether the window's native close button is enabled or not.",
+          "default": false,
+          "type": "boolean"
+        },
         "setTitle": {
           "description": "Allows changing the window title.",
           "default": false,

部分文件因为文件数量过多而无法显示