Browse Source

feat(core): window API (#1225)

Lucas Fernandes Nogueira 4 năm trước cách đây
mục cha
commit
a3d6dff216

+ 6 - 0
.changes/window-api.md

@@ -0,0 +1,6 @@
+---
+"api": minor
+"tauri": minor
+---
+
+Added window management APIs.

+ 311 - 1
api/src/window.ts

@@ -1,5 +1,18 @@
 import { invoke } from './tauri'
 
+/**
+ * Updates the window resizable flag.
+ */
+function setResizable(resizable: boolean): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setResizable',
+      resizable
+    }
+  })
+}
+
 /**
  * sets the window title
  *
@@ -15,4 +28,301 @@ function setTitle(title: string): void {
   })
 }
 
-export { setTitle }
+/**
+ * Maximizes the window.
+ */
+function maximize(): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'maximize'
+    }
+  })
+}
+
+/**
+ * Unmaximizes the window.
+ */
+function unmaximize(): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'unmaximize'
+    }
+  })
+}
+
+/**
+ * Minimizes the window.
+ */
+function minimize(): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'minimize'
+    }
+  })
+}
+
+/**
+ * Unminimizes the window.
+ */
+function unminimize(): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'unminimize'
+    }
+  })
+}
+
+/**
+ * Sets the window visibility to true.
+ */
+function show(): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'show'
+    }
+  })
+}
+
+/**
+ * Sets the window visibility to false.
+ */
+function hide(): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'hide'
+    }
+  })
+}
+
+/**
+ * Sets the window transparent flag.
+ *
+ * @param {boolean} transparent whether the the window should be transparent or not
+ */
+function setTransparent(transparent: boolean): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setTransparent',
+      transparent
+    }
+  })
+}
+
+/**
+ * Whether the window should have borders and bars.
+ *
+ * @param {boolean} decorations whether the window should have borders and bars
+ */
+function setDecorations(decorations: boolean): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setDecorations',
+      decorations
+    }
+  })
+}
+
+/**
+ * Whether the window should always be on top of other windows.
+ *
+ * @param {boolean} alwaysOnTop whether the window should always be on top of other windows or not
+ */
+function setAlwaysOnTop(alwaysOnTop: boolean): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setAlwaysOnTop',
+      alwaysOnTop
+    }
+  })
+}
+
+/**
+ * Sets the window width.
+ *
+ * @param {number} width the new window width
+ */
+function setWidth(width: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setWidth',
+      width
+    }
+  })
+}
+
+/**
+ * Sets the window height.
+ *
+ * @param {number} height the new window height
+ */
+function setHeight(height: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setHeight',
+      height
+    }
+  })
+}
+
+/**
+ * Resizes the window.
+ *
+ * @param {number} width the new window width
+ * @param {number} height the new window height
+ */
+function resize(width: number, height: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'resize',
+      width,
+      height,
+    }
+  })
+}
+
+/**
+ * Sets the window min size.
+ *
+ * @param {number} minWidth the new window min width
+ * @param {number} minHeight the new window min height
+ */
+function setMinSize(minWidth: number, minHeight: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setMinSize',
+      minWidth,
+      minHeight
+    }
+  })
+}
+
+/**
+ * Sets the window max size.
+ *
+ * @param {number} maxWidth the new window max width
+ * @param {number} maxHeight the new window max height
+ */
+function setMaxSize(maxWidth: number, maxHeight: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setMaxSize',
+      maxWidth,
+      maxHeight
+    }
+  })
+}
+
+/**
+ * Sets the window x position.
+ *
+ * @param {number} x the new window x position
+ */
+function setX(x: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setX',
+      x
+    }
+  })
+}
+
+/**
+ * Sets the window y position.
+ *
+ * @param {number} y the new window y position
+ */
+function setY(y: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setY',
+      y
+    }
+  })
+}
+
+/**
+ * Sets the window position.
+ *
+ * @param {number} x the new window x position
+ * @param {number} y the new window y position
+ */
+function setPosition(x: number, y: number): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setPosition',
+      x,
+      y
+    }
+  })
+}
+
+/**
+ * Sets the window fullscreen state.
+ *
+ * @param {boolean} fullscreen whether the window should go to fullscreen or not
+ */
+function setFullscreen(fullscreen: boolean): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setFullscreen',
+      fullscreen
+    }
+  })
+}
+
+/**
+ * Sets the window icon
+ *
+ * @param {string | number[]} icon icon bytes or path to the icon file
+ */
+function setIcon(icon: 'string' | number[]): void {
+  invoke({
+    module: 'Window',
+    message: {
+      cmd: 'setIcon',
+      icon
+    }
+  })
+}
+
+export {
+  setResizable,
+  setTitle,
+  maximize,
+  unmaximize,
+  minimize,
+  unminimize,
+  show,
+  hide,
+  setTransparent,
+  setDecorations,
+  setAlwaysOnTop,
+  setWidth,
+  setHeight,
+  resize,
+  setMinSize,
+  setMaxSize,
+  setX,
+  setY,
+  setPosition,
+  setFullscreen,
+  setIcon
+}

+ 16 - 4
tauri/Cargo.toml

@@ -32,7 +32,7 @@ thiserror = "1.0.23"
 once_cell = "1.5.2"
 tauri-api = { version = "0.7.5", path = "../tauri-api" }
 tauri-macros = { version = "0.1", path = "../tauri-macros" }
-wry = { git = "https://github.com/tauri-apps/wry", rev = "f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4" }
+wry = { git = "https://github.com/tauri-apps/wry", rev = "b36b3e2d07edddf2ef49dcc901ae2c5888873ad2" }
 
 [target."cfg(target_os = \"windows\")".dependencies]
 runas = "0.2"
@@ -50,6 +50,9 @@ serde = { version = "1.0", features = [ "derive" ] }
 cli = [ "tauri-api/cli" ]
 embedded-server = [ "tiny_http" ]
 all-api = [ "tauri-api/notification" ]
+updater = [ ]
+
+# FS
 read-text-file = [ ]
 read-binary-file = [ ]
 write-file = [ ]
@@ -61,14 +64,23 @@ remove-dir = [ ]
 remove-file = [ ]
 rename-file = [ ]
 path-api = [ ]
-set-title = [ ]
+event = [ ]
+
+# window
+window = [ ]
+
+#shell
 execute = [ ]
 open = [ ]
-event = [ ]
-updater = [ ]
+
+# dialog
 open-dialog = [ ]
 save-dialog = [ ]
+
+# HTTP
 http-request = [ ]
+
+# notification
 notification = [ "tauri-api/notification" ]
 
 [[example]]

+ 3 - 3
tauri/build.rs

@@ -23,10 +23,10 @@ fn main() {
     path_api: { any(all_api, feature = "path-api") },
 
     // window
-    set_title: { any(all_api, feature = "set-title") },
-    open: { any(all_api, feature = "open") },
+    window: { any(all_api, feature = "window") },
 
-    // process
+    // shell
+    open: { any(all_api, feature = "open") },
     execute: { any(all_api, feature = "execute") },
 
     // event

+ 2 - 2
tauri/examples/api/package.json

@@ -17,7 +17,7 @@
     "svelte": "3.32.2"
   },
   "dependencies": {
-    "sirv-cli": "1.0.11",
-    "@tauri-apps/api": "link:../../../api"
+    "@tauri-apps/api": "link:../../../api",
+    "sirv-cli": "1.0.11"
   }
 }

+ 120 - 1
tauri/examples/api/src-tauri/Cargo.lock

@@ -201,6 +201,12 @@ version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
 
+[[package]]
+name = "bytemuck"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0"
+
 [[package]]
 name = "byteorder"
 version = "1.4.2"
@@ -374,6 +380,12 @@ dependencies = [
  "objc",
 ]
 
+[[package]]
+name = "color_quant"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
+
 [[package]]
 name = "const-sha1"
 version = "0.2.0"
@@ -574,6 +586,16 @@ dependencies = [
  "libdbus-sys",
 ]
 
+[[package]]
+name = "deflate"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
+dependencies = [
+ "adler32",
+ "byteorder",
+]
+
 [[package]]
 name = "derivative"
 version = "2.2.0"
@@ -924,6 +946,16 @@ dependencies = [
  "wasi 0.10.2+wasi-snapshot-preview1",
 ]
 
+[[package]]
+name = "gif"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4"
+dependencies = [
+ "color_quant",
+ "weezl",
+]
+
 [[package]]
 name = "gimli"
 version = "0.23.0"
@@ -1118,6 +1150,25 @@ dependencies = [
  "unicode-normalization",
 ]
 
+[[package]]
+name = "image"
+version = "0.23.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d"
+dependencies = [
+ "bytemuck",
+ "byteorder",
+ "color_quant",
+ "gif",
+ "jpeg-decoder",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+ "png",
+ "scoped_threadpool",
+ "tiff",
+]
+
 [[package]]
 name = "indexmap"
 version = "1.6.1"
@@ -1186,6 +1237,15 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
 
+[[package]]
+name = "jpeg-decoder"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
+dependencies = [
+ "rayon",
+]
+
 [[package]]
 name = "js-sys"
 version = "0.3.47"
@@ -1514,6 +1574,28 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "num-iter"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.14"
@@ -1773,6 +1855,18 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
 
+[[package]]
+name = "png"
+version = "0.16.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
+dependencies = [
+ "bitflags 1.2.1",
+ "crc32fast",
+ "deflate",
+ "miniz_oxide 0.3.7",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.10"
@@ -2087,6 +2181,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 
+[[package]]
+name = "scoped_threadpool"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
@@ -2516,6 +2616,17 @@ dependencies = [
  "syn 1.0.60",
 ]
 
+[[package]]
+name = "tiff"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
+dependencies = [
+ "jpeg-decoder",
+ "miniz_oxide 0.4.3",
+ "weezl",
+]
+
 [[package]]
 name = "time"
 version = "0.1.43"
@@ -2888,6 +2999,12 @@ dependencies = [
  "soup-sys",
 ]
 
+[[package]]
+name = "weezl"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
+
 [[package]]
 name = "which"
 version = "3.1.1"
@@ -3094,15 +3211,17 @@ dependencies = [
 [[package]]
 name = "wry"
 version = "0.4.1"
-source = "git+https://github.com/tauri-apps/wry?rev=f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4#f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4"
+source = "git+https://github.com/tauri-apps/wry?rev=b36b3e2d07edddf2ef49dcc901ae2c5888873ad2#b36b3e2d07edddf2ef49dcc901ae2c5888873ad2"
 dependencies = [
  "cc",
  "cocoa",
  "core-graphics 0.22.2",
  "gdk",
+ "gdk-pixbuf",
  "gio",
  "glib",
  "gtk",
+ "image",
  "libc",
  "objc",
  "once_cell",

+ 177 - 3
tauri/examples/api/src/components/Window.svelte

@@ -1,20 +1,194 @@
 <script>
-  import { setTitle } from "@tauri-apps/api/window";
+  import {
+    setResizable,
+    setTitle as setTitle,
+    maximize,
+    unmaximize,
+    minimize,
+    unminimize,
+    show,
+    hide,
+    setTransparent,
+    setDecorations,
+    setAlwaysOnTop,
+    setWidth,
+    setHeight,
+    // resize,
+    setMinSize,
+    setMaxSize,
+    setX,
+    setY,
+    // setPosition,
+    setFullscreen,
+    setIcon
+  } from "@tauri-apps/api/window";
+  import { open as openDialog } from '@tauri-apps/api/dialog'
   import { open } from "@tauri-apps/api/shell";
 
   let urlValue = "https://tauri.studio";
+  let resizable = true
+  let maximized = false
+  let transparent = false
+  let decorations = false
+  let alwaysOnTop = false
+  let fullscreen = false
+  let width = 600
+  let height = 600
+  let minWidth = 600
+  let minHeight = 600
+  let maxWidth = null
+  let maxHeight = null
+  let x = 300
+  let y = 300
+
   let windowTitle = 'Awesome Tauri Example!';
 
   function openUrl() {
     open(urlValue);
   }
 
-  function setWindowTitle() {
+  function setTitle_() {
     setTitle(windowTitle);
   }
+
+  function hide_() {
+    hide()
+    setTimeout(show, 2000)
+  }
+
+  function minimize_() {
+    minimize()
+    setTimeout(unminimize, 2000)
+  }
+
+  function getIcon() {
+    openDialog({
+      multiple: false
+    }).then(setIcon)
+  }
+
+  $: setResizable(resizable)
+  $: maximized ? maximize() : unmaximize()
+  $: setTransparent(transparent)
+  $: setDecorations(decorations)
+  $: setAlwaysOnTop(alwaysOnTop)
+  $: setFullscreen(fullscreen)
+
+  $: setWidth(width)
+  $: setHeight(height)
+  $: minWidth && minHeight && setMinSize(minWidth, minHeight)
+  $: maxWidth && maxHeight && setMaxSize(maxWidth, maxHeight)
+  $: setX(x)
+  $: setY(y)
 </script>
 
-<form style="margin-top: 24px" on:submit|preventDefault={setWindowTitle}>
+<style>
+  .flex {
+    display: flex;
+  }
+
+  .flex-row {
+    flex-direction: row;
+  }
+
+  .flex-column {
+    flex-direction: column;
+  }
+
+  .grow {
+    flex-grow: 1;
+  }
+
+  .window-controls input {
+    width: 50px;
+  }
+</style>
+
+<div class="flex flex-column">
+  <div>
+    <label>
+      <input type="checkbox" bind:checked={resizable}>
+      Resizable
+    </label>
+    <label>
+      <input type="checkbox" bind:checked={maximized}>
+      Maximize
+    </label>
+    <button title="Unminimizes after 2 seconds" on:click={minimize_}>
+      Minimize
+    </button>
+    <button title="Visible again after 2 seconds" on:click={hide_}>
+      Hide
+    </button>
+    <label>
+      <input type="checkbox" bind:checked={transparent}>
+      Transparent
+    </label>
+    <label>
+      <input type="checkbox" bind:checked={decorations}>
+      Has decorations
+    </label>
+    <label>
+      <input type="checkbox" bind:checked={alwaysOnTop}>
+      Always on top
+    </label>
+    <label>
+      <input type="checkbox" bind:checked={fullscreen}>
+      Fullscreen
+    </label>
+    <button on:click={getIcon}>
+      Change icon
+    </button>
+  </div>
+  <div>
+    <div class="window-controls flex flex-row">
+      <div class="flex flex-column grow">
+        <div>
+          X
+          <input type="number" bind:value={x} min="0">
+        </div>
+        <div>
+          Y
+          <input type="number" bind:value={y} min="0">
+        </div>
+      </div>
+
+      <div class="flex flex-column grow">
+        <div>
+          Width
+          <input type="number" bind:value={width} min="400">
+        </div>
+        <div>
+          Height
+          <input type="number" bind:value={height} min="400">
+        </div>
+      </div>
+
+      <div class="flex flex-column grow">
+        <div>
+          Min width
+          <input type="number" bind:value={minWidth}>
+        </div>
+        <div>
+          Min height
+          <input type="number" bind:value={minHeight}>
+        </div>
+      </div>
+
+      <div class="flex flex-column grow">
+        <div>
+          Max width
+          <input type="number" bind:value={maxWidth} min="400">
+        </div>
+        <div>
+          Max height
+          <input type="number" bind:value={maxHeight} min="400">
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+<form style="margin-top: 24px" on:submit|preventDefault={setTitle_}>
   <input id="title" bind:value={windowTitle} />
   <button class="button" type="submit">Set title</button>
 </form>

+ 49 - 53
tauri/examples/api/yarn.lock

@@ -63,12 +63,13 @@
     picomatch "^2.2.2"
 
 "@tauri-apps/api@link:../../../api":
-  version "0.1.0"
+  version "0.0.0"
+  uid ""
 
 "@types/estree@*":
-  version "0.0.45"
-  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
-  integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
+  version "0.0.46"
+  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
+  integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
 
 "@types/estree@0.0.39":
   version "0.0.39"
@@ -76,9 +77,9 @@
   integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
 
 "@types/node@*":
-  version "14.0.14"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce"
-  integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==
+  version "14.14.27"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.27.tgz#c7127f8da0498993e13b1a42faf1303d3110d2f2"
+  integrity sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng==
 
 "@types/resolve@1.17.1":
   version "1.17.1"
@@ -113,9 +114,9 @@ balanced-match@^1.0.0:
   integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
 
 binary-extensions@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
-  integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+  integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
 
 brace-expansion@^1.1.7:
   version "1.1.11"
@@ -138,9 +139,9 @@ buffer-from@^1.0.0:
   integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
 
 builtin-modules@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
-  integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"
+  integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==
 
 chalk@^2.0.0:
   version "2.4.2"
@@ -152,9 +153,9 @@ chalk@^2.0.0:
     supports-color "^5.3.0"
 
 chokidar@^3.3.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
-  integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
+  integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
   dependencies:
     anymatch "~3.1.1"
     braces "~3.0.2"
@@ -162,9 +163,9 @@ chokidar@^3.3.0:
     is-binary-path "~2.1.0"
     is-glob "~4.0.1"
     normalize-path "~3.0.0"
-    readdirp "~3.4.0"
+    readdirp "~3.5.0"
   optionalDependencies:
-    fsevents "~2.1.2"
+    fsevents "~2.3.1"
 
 color-convert@^1.9.0:
   version "1.9.3"
@@ -235,15 +236,10 @@ fs.realpath@^1.0.0:
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
   integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
 
-fsevents@~2.1.2:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
-  integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
-
 fsevents@~2.3.1:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
-  integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
 
 function-bind@^1.1.1:
   version "1.1.1"
@@ -311,7 +307,7 @@ is-binary-path@~2.1.0:
   dependencies:
     binary-extensions "^2.0.0"
 
-is-core-module@^2.1.0:
+is-core-module@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
   integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
@@ -367,9 +363,9 @@ kleur@^3.0.0:
   integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
 
 livereload-js@^3.1.0:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.2.3.tgz#64beff07ce5b2a74485d1a08c2ec04ac68e021bc"
-  integrity sha512-dXL/WgTGI2K3oeYX/z1lngFXSKtjCB2j7n9WSSluoU6/6+N4LWNoMiCBFNgn8dh3luBn4JBajVSvM5I7Xn6SLA==
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.3.1.tgz#61f887468086762e61fb2987412cf9d1dda99202"
+  integrity sha512-CBu1gTEfzVhlOK1WASKAAJ9Qx1fHECTq0SUB67sfxwQssopTyvzqTlgl+c0h9pZ6V+Fzd2rc510ppuNusg9teQ==
 
 livereload@^0.9.1:
   version "0.9.1"
@@ -382,9 +378,9 @@ livereload@^0.9.1:
     ws "^6.2.1"
 
 local-access@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.0.1.tgz#5121258146d64e869046c642ea4f1dd39ff942bb"
-  integrity sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA==
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.1.0.tgz#e007c76ba2ca83d5877ba1a125fc8dfe23ba4798"
+  integrity sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==
 
 magic-string@^0.25.7:
   version "0.25.7"
@@ -399,9 +395,9 @@ merge-stream@^2.0.0:
   integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
 
 mime@^2.3.1:
-  version "2.4.6"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
-  integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.0.tgz#2b4af934401779806ee98026bb42e8c1ae1876b1"
+  integrity sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==
 
 minimatch@^3.0.4:
   version "3.0.4"
@@ -411,9 +407,9 @@ minimatch@^3.0.4:
     brace-expansion "^1.1.7"
 
 mri@^1.1.0:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.5.tgz#ce21dba2c69f74a9b7cf8a1ec62307e089e223e0"
-  integrity sha512-d2RKzMD4JNyHMbnbWnznPaa8vbdlq/4pNZ3IgdaGrVbBhebBsGUUE/6qorTMYNS6TwuH3ilfOlD2bf4Igh8CKg==
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6"
+  integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
 
 normalize-path@^3.0.0, normalize-path@~3.0.0:
   version "3.0.0"
@@ -428,9 +424,9 @@ once@^1.3.0:
     wrappy "1"
 
 "opts@>= 1.2.0":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.0.tgz#c0b2cebdf53eaeafc21ed844e34773758dcf41e2"
-  integrity sha512-rPleeyX48sBEc4aj7rAok5dCbvRdYpdbIdSRR4gnIK98a7Rvd4l3wlv4YHQr2mwPQTpKQiw8uipi/WoyItDINg==
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1"
+  integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==
 
 path-is-absolute@^1.0.0:
   version "1.0.1"
@@ -454,10 +450,10 @@ randombytes@^2.1.0:
   dependencies:
     safe-buffer "^5.1.0"
 
-readdirp@~3.4.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
-  integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==
+readdirp@~3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
+  integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
   dependencies:
     picomatch "^2.2.1"
 
@@ -467,11 +463,11 @@ require-relative@^0.8.7:
   integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
 
 resolve@^1.17.0, resolve@^1.19.0:
-  version "1.19.0"
-  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
-  integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
+  version "1.20.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
+  integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
   dependencies:
-    is-core-module "^2.1.0"
+    is-core-module "^2.2.0"
     path-parse "^1.0.6"
 
 rollup-plugin-livereload@2.0.0:
@@ -603,9 +599,9 @@ svelte@3.32.2:
   integrity sha512-Zxh1MQQl/+vnToKbU1Per+PoMN8Jb2MeKJcGxiOsCGR677hXw7jkMfbnNXq33+dxIzV/HfA4xtoSPJrqeB0VUg==
 
 terser@^5.0.0:
-  version "5.5.1"
-  resolved "https://registry.yarnpkg.com/terser/-/terser-5.5.1.tgz#540caa25139d6f496fdea056e414284886fb2289"
-  integrity sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.0.tgz#138cdf21c5e3100b1b3ddfddf720962f88badcd2"
+  integrity sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==
   dependencies:
     commander "^2.20.0"
     source-map "~0.7.2"

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
tauri/examples/communication/dist/__tauri.js


+ 120 - 1
tauri/examples/communication/src-tauri/Cargo.lock

@@ -201,6 +201,12 @@ version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
 
+[[package]]
+name = "bytemuck"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0"
+
 [[package]]
 name = "byteorder"
 version = "1.4.2"
@@ -374,6 +380,12 @@ dependencies = [
  "objc",
 ]
 
+[[package]]
+name = "color_quant"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
+
 [[package]]
 name = "const-sha1"
 version = "0.2.0"
@@ -574,6 +586,16 @@ dependencies = [
  "libdbus-sys",
 ]
 
+[[package]]
+name = "deflate"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
+dependencies = [
+ "adler32",
+ "byteorder",
+]
+
 [[package]]
 name = "derivative"
 version = "2.2.0"
@@ -924,6 +946,16 @@ dependencies = [
  "wasi 0.10.2+wasi-snapshot-preview1",
 ]
 
+[[package]]
+name = "gif"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4"
+dependencies = [
+ "color_quant",
+ "weezl",
+]
+
 [[package]]
 name = "gimli"
 version = "0.23.0"
@@ -1118,6 +1150,25 @@ dependencies = [
  "unicode-normalization",
 ]
 
+[[package]]
+name = "image"
+version = "0.23.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d"
+dependencies = [
+ "bytemuck",
+ "byteorder",
+ "color_quant",
+ "gif",
+ "jpeg-decoder",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+ "png",
+ "scoped_threadpool",
+ "tiff",
+]
+
 [[package]]
 name = "indexmap"
 version = "1.6.1"
@@ -1186,6 +1237,15 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
 
+[[package]]
+name = "jpeg-decoder"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
+dependencies = [
+ "rayon",
+]
+
 [[package]]
 name = "js-sys"
 version = "0.3.47"
@@ -1514,6 +1574,28 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "num-iter"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.14"
@@ -1773,6 +1855,18 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
 
+[[package]]
+name = "png"
+version = "0.16.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
+dependencies = [
+ "bitflags 1.2.1",
+ "crc32fast",
+ "deflate",
+ "miniz_oxide 0.3.7",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.10"
@@ -2087,6 +2181,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 
+[[package]]
+name = "scoped_threadpool"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
@@ -2516,6 +2616,17 @@ dependencies = [
  "syn 1.0.60",
 ]
 
+[[package]]
+name = "tiff"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
+dependencies = [
+ "jpeg-decoder",
+ "miniz_oxide 0.4.3",
+ "weezl",
+]
+
 [[package]]
 name = "time"
 version = "0.1.43"
@@ -2888,6 +2999,12 @@ dependencies = [
  "soup-sys",
 ]
 
+[[package]]
+name = "weezl"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
+
 [[package]]
 name = "which"
 version = "3.1.1"
@@ -3094,15 +3211,17 @@ dependencies = [
 [[package]]
 name = "wry"
 version = "0.4.1"
-source = "git+https://github.com/tauri-apps/wry?rev=f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4#f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4"
+source = "git+https://github.com/tauri-apps/wry?rev=b36b3e2d07edddf2ef49dcc901ae2c5888873ad2#b36b3e2d07edddf2ef49dcc901ae2c5888873ad2"
 dependencies = [
  "cc",
  "cocoa",
  "core-graphics 0.22.2",
  "gdk",
+ "gdk-pixbuf",
  "gio",
  "glib",
  "gtk",
+ "image",
  "libc",
  "objc",
  "once_cell",

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
tauri/examples/multiwindow/dist/__tauri.js


+ 120 - 1
tauri/examples/multiwindow/src-tauri/Cargo.lock

@@ -188,6 +188,12 @@ version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
 
+[[package]]
+name = "bytemuck"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0"
+
 [[package]]
 name = "byteorder"
 version = "1.4.2"
@@ -331,6 +337,12 @@ dependencies = [
  "objc",
 ]
 
+[[package]]
+name = "color_quant"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
+
 [[package]]
 name = "const-sha1"
 version = "0.2.0"
@@ -531,6 +543,16 @@ dependencies = [
  "libdbus-sys",
 ]
 
+[[package]]
+name = "deflate"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
+dependencies = [
+ "adler32",
+ "byteorder",
+]
+
 [[package]]
 name = "derivative"
 version = "2.2.0"
@@ -881,6 +903,16 @@ dependencies = [
  "wasi 0.10.2+wasi-snapshot-preview1",
 ]
 
+[[package]]
+name = "gif"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4"
+dependencies = [
+ "color_quant",
+ "weezl",
+]
+
 [[package]]
 name = "gimli"
 version = "0.23.0"
@@ -1069,6 +1101,25 @@ dependencies = [
  "unicode-normalization",
 ]
 
+[[package]]
+name = "image"
+version = "0.23.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d"
+dependencies = [
+ "bytemuck",
+ "byteorder",
+ "color_quant",
+ "gif",
+ "jpeg-decoder",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+ "png",
+ "scoped_threadpool",
+ "tiff",
+]
+
 [[package]]
 name = "instant"
 version = "0.1.9"
@@ -1127,6 +1178,15 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
 
+[[package]]
+name = "jpeg-decoder"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
+dependencies = [
+ "rayon",
+]
+
 [[package]]
 name = "js-sys"
 version = "0.3.47"
@@ -1455,6 +1515,28 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "num-iter"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.14"
@@ -1708,6 +1790,18 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
 
+[[package]]
+name = "png"
+version = "0.16.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
+dependencies = [
+ "bitflags 1.2.1",
+ "crc32fast",
+ "deflate",
+ "miniz_oxide 0.3.7",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.10"
@@ -2022,6 +2116,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 
+[[package]]
+name = "scoped_threadpool"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
@@ -2426,6 +2526,17 @@ dependencies = [
  "syn 1.0.60",
 ]
 
+[[package]]
+name = "tiff"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
+dependencies = [
+ "jpeg-decoder",
+ "miniz_oxide 0.4.3",
+ "weezl",
+]
+
 [[package]]
 name = "time"
 version = "0.1.43"
@@ -2786,6 +2897,12 @@ dependencies = [
  "soup-sys",
 ]
 
+[[package]]
+name = "weezl"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
+
 [[package]]
 name = "which"
 version = "3.1.1"
@@ -2992,15 +3109,17 @@ dependencies = [
 [[package]]
 name = "wry"
 version = "0.4.1"
-source = "git+https://github.com/tauri-apps/wry?rev=f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4#f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4"
+source = "git+https://github.com/tauri-apps/wry?rev=b36b3e2d07edddf2ef49dcc901ae2c5888873ad2#b36b3e2d07edddf2ef49dcc901ae2c5888873ad2"
 dependencies = [
  "cc",
  "cocoa",
  "core-graphics 0.22.2",
  "gdk",
+ "gdk-pixbuf",
  "gio",
  "glib",
  "gtk",
+ "image",
  "libc",
  "objc",
  "once_cell",

+ 114 - 4
tauri/src/app/webview_manager.rs

@@ -1,7 +1,7 @@
 use std::collections::HashMap;
 
 use crate::{
-  webview::{Event, Message},
+  webview::{Event, Icon, Message},
   ApplicationDispatcherExt,
 };
 
@@ -47,11 +47,121 @@ impl<A: ApplicationDispatcherExt> WebviewDispatcher<A> {
     self.0.send_message(Message::EvalScript(js.to_string()))
   }
 
+  /// Updates the window resizable flag.
+  pub fn set_resizable(&self, resizable: bool) {
+    self.0.send_message(Message::SetResizable(resizable))
+  }
+
   /// Updates the window title.
   pub fn set_title(&self, title: &str) {
-    self
-      .0
-      .send_message(Message::SetWindowTitle(title.to_string()))
+    self.0.send_message(Message::SetTitle(title.to_string()))
+  }
+
+  /// Maximizes the window.
+  pub fn maximize(&self) {
+    self.0.send_message(Message::Maximize)
+  }
+
+  /// Unmaximizes the window.
+  pub fn unmaximize(&self) {
+    self.0.send_message(Message::Unmaximize)
+  }
+
+  /// Minimizes the window.
+  pub fn minimize(&self) {
+    self.0.send_message(Message::Minimize)
+  }
+
+  /// Unminimizes the window.
+  pub fn unminimize(&self) {
+    self.0.send_message(Message::Unminimize)
+  }
+
+  /// Sets the window visibility to true.
+  pub fn show(&self) {
+    self.0.send_message(Message::Show)
+  }
+
+  /// Sets the window visibility to false.
+  pub fn hide(&self) {
+    self.0.send_message(Message::Hide)
+  }
+
+  /// Sets the window transparent flag.
+  pub fn set_transparent(&self, transparent: bool) {
+    self.0.send_message(Message::SetTransparent(transparent))
+  }
+
+  /// Whether the window should have borders and bars.
+  pub fn set_decorations(&self, decorations: bool) {
+    self.0.send_message(Message::SetDecorations(decorations))
+  }
+
+  /// Whether the window should always be on top of other windows.
+  pub fn set_always_on_top(&self, always_on_top: bool) {
+    self.0.send_message(Message::SetAlwaysOnTop(always_on_top))
+  }
+
+  /// Sets the window width.
+  pub fn set_width(&self, width: impl Into<f64>) {
+    self.0.send_message(Message::SetWidth(width.into()))
+  }
+
+  /// Sets the window height.
+  pub fn set_height(&self, height: impl Into<f64>) {
+    self.0.send_message(Message::SetHeight(height.into()))
+  }
+
+  /// Resizes the window.
+  pub fn resize(&self, width: impl Into<f64>, height: impl Into<f64>) {
+    self.0.send_message(Message::Resize {
+      width: width.into(),
+      height: height.into(),
+    })
+  }
+
+  /// Sets the window min size.
+  pub fn set_min_size(&self, min_width: impl Into<f64>, min_height: impl Into<f64>) {
+    self.0.send_message(Message::SetMinSize {
+      min_width: min_width.into(),
+      min_height: min_height.into(),
+    })
+  }
+
+  /// Sets the window max size.
+  pub fn set_max_size(&self, max_width: impl Into<f64>, max_height: impl Into<f64>) {
+    self.0.send_message(Message::SetMaxSize {
+      max_width: max_width.into(),
+      max_height: max_height.into(),
+    })
+  }
+
+  /// Sets the window x position.
+  pub fn set_x(&self, x: impl Into<f64>) {
+    self.0.send_message(Message::SetX(x.into()))
+  }
+
+  /// Sets the window y position.
+  pub fn set_y(&self, y: impl Into<f64>) {
+    self.0.send_message(Message::SetY(y.into()))
+  }
+
+  /// Sets the window position.
+  pub fn set_position(&self, x: impl Into<f64>, y: impl Into<f64>) {
+    self.0.send_message(Message::SetPosition {
+      x: x.into(),
+      y: y.into(),
+    })
+  }
+
+  /// Sets the window fullscreen state.
+  pub fn set_fullscreen(&self, fullscreen: bool) {
+    self.0.send_message(Message::SetFullscreen(fullscreen))
+  }
+
+  /// Sets the window icon.
+  pub fn set_icon(&self, icon: Icon) {
+    self.0.send_message(Message::SetIcon(icon))
   }
 }
 

+ 107 - 7
tauri/src/endpoints/window.rs

@@ -1,11 +1,84 @@
+use crate::webview::Icon;
 use serde::Deserialize;
 
+#[derive(Deserialize)]
+#[serde(untagged)]
+pub enum IconDto {
+  File(String),
+  Raw(Vec<u8>),
+}
+
+impl Into<Icon> for IconDto {
+  fn into(self) -> Icon {
+    match self {
+      Self::File(path) => Icon::File(path),
+      Self::Raw(raw) => Icon::Raw(raw),
+    }
+  }
+}
+
 /// The API descriptor.
 #[derive(Deserialize)]
 #[serde(tag = "cmd", rename_all = "camelCase")]
 pub enum Cmd {
-  /// The set webview title API.
-  SetTitle { title: String },
+  SetResizable {
+    resizable: bool,
+  },
+  SetTitle {
+    title: String,
+  },
+  Maximize,
+  Unmaximize,
+  Minimize,
+  Unminimize,
+  Show,
+  Hide,
+  SetTransparent {
+    transparent: bool,
+  },
+  SetDecorations {
+    decorations: bool,
+  },
+  #[serde(rename_all = "camelCase")]
+  SetAlwaysOnTop {
+    always_on_top: bool,
+  },
+  SetWidth {
+    width: f64,
+  },
+  SetHeight {
+    height: f64,
+  },
+  Resize {
+    width: f64,
+    height: f64,
+  },
+  #[serde(rename_all = "camelCase")]
+  SetMinSize {
+    min_width: f64,
+    min_height: f64,
+  },
+  #[serde(rename_all = "camelCase")]
+  SetMaxSize {
+    max_width: f64,
+    max_height: f64,
+  },
+  SetX {
+    x: f64,
+  },
+  SetY {
+    y: f64,
+  },
+  SetPosition {
+    x: f64,
+    y: f64,
+  },
+  SetFullscreen {
+    fullscreen: bool,
+  },
+  SetIcon {
+    icon: IconDto,
+  },
 }
 
 impl Cmd {
@@ -13,11 +86,38 @@ impl Cmd {
     self,
     webview_manager: &crate::WebviewManager<D>,
   ) -> crate::Result<()> {
-    match self {
-      Self::SetTitle { title } => {
-        webview_manager.current_webview()?.set_title(&title);
-        #[cfg(not(set_title))]
-        throw_allowlist_error(webview_manager, "title");
+    if cfg!(not(window)) {
+      super::throw_allowlist_error(webview_manager, "setTitle");
+    } else {
+      let current_webview = webview_manager.current_webview()?;
+      match self {
+        Self::SetResizable { resizable } => current_webview.set_resizable(resizable),
+        Self::SetTitle { title } => current_webview.set_title(&title),
+        Self::Maximize => current_webview.maximize(),
+        Self::Unmaximize => current_webview.unmaximize(),
+        Self::Minimize => current_webview.minimize(),
+        Self::Unminimize => current_webview.unminimize(),
+        Self::Show => current_webview.show(),
+        Self::Hide => current_webview.hide(),
+        Self::SetTransparent { transparent } => current_webview.set_transparent(transparent),
+        Self::SetDecorations { decorations } => current_webview.set_decorations(decorations),
+        Self::SetAlwaysOnTop { always_on_top } => current_webview.set_always_on_top(always_on_top),
+        Self::SetWidth { width } => current_webview.set_width(width),
+        Self::SetHeight { height } => current_webview.set_height(height),
+        Self::Resize { width, height } => current_webview.resize(width, height),
+        Self::SetMinSize {
+          min_width,
+          min_height,
+        } => current_webview.set_min_size(min_width, min_height),
+        Self::SetMaxSize {
+          max_width,
+          max_height,
+        } => current_webview.set_max_size(max_width, max_height),
+        Self::SetX { x } => current_webview.set_x(x),
+        Self::SetY { y } => current_webview.set_y(y),
+        Self::SetPosition { x, y } => current_webview.set_position(x, y),
+        Self::SetFullscreen { fullscreen } => current_webview.set_fullscreen(fullscreen),
+        Self::SetIcon { icon } => current_webview.set_icon(icon.into()),
       }
     }
     Ok(())

+ 3 - 0
tauri/src/error.rs

@@ -31,6 +31,9 @@ pub enum Error {
   /// Failed to decode base64.
   #[error("Failed to decode base64 string: {0}")]
   Base64Decode(#[from] base64::DecodeError),
+  /// Failed to load window icon.
+  #[error("invalid icon: {0}")]
+  InvalidIcon(String),
 }
 
 impl From<serde_json::Error> for Error {

+ 29 - 1
tauri/src/webview.rs

@@ -8,10 +8,38 @@ pub enum Event {
   Run(crate::SyncTask),
 }
 
+pub enum Icon {
+  File(String),
+  Raw(Vec<u8>),
+}
+
 pub enum Message {
+  // webview messages
   EvalScript(String),
-  SetWindowTitle(String),
+  // custom messages
   Event(Event),
+  // window messages
+  SetResizable(bool),
+  SetTitle(String),
+  Maximize,
+  Unmaximize,
+  Minimize,
+  Unminimize,
+  Show,
+  Hide,
+  SetTransparent(bool),
+  SetDecorations(bool),
+  SetAlwaysOnTop(bool),
+  SetWidth(f64),
+  SetHeight(f64),
+  Resize { width: f64, height: f64 },
+  SetMinSize { min_width: f64, min_height: f64 },
+  SetMaxSize { max_width: f64, max_height: f64 },
+  SetX(f64),
+  SetY(f64),
+  SetPosition { x: f64, y: f64 },
+  SetFullscreen(bool),
+  SetIcon(Icon),
 }
 
 /// The window builder.

+ 87 - 13
tauri/src/webview/wry.rs

@@ -1,5 +1,5 @@
 use super::{
-  ApplicationDispatcherExt, ApplicationExt, Callback, Event, Message, WebviewBuilderExt,
+  ApplicationDispatcherExt, ApplicationExt, Callback, Event, Icon, Message, WebviewBuilderExt,
   WindowBuilderExt,
 };
 
@@ -9,7 +9,25 @@ use once_cell::sync::Lazy;
 
 use crate::plugin::PluginStore;
 
-use std::sync::{Arc, Mutex};
+use std::{
+  convert::{TryFrom, TryInto},
+  sync::{Arc, Mutex},
+};
+
+impl TryInto<wry::Icon> for Icon {
+  type Error = crate::Error;
+  fn try_into(self) -> Result<wry::Icon, Self::Error> {
+    let icon = match self {
+      Self::File(path) => {
+        wry::Icon::from_file(path).map_err(|e| crate::Error::InvalidIcon(e.to_string()))?
+      }
+      Self::Raw(raw) => {
+        wry::Icon::from_bytes(raw).map_err(|e| crate::Error::InvalidIcon(e.to_string()))?
+      }
+    };
+    Ok(icon)
+  }
+}
 
 impl WindowBuilderExt for wry::AppWindowAttributes {
   type Window = Self;
@@ -136,26 +154,82 @@ pub struct WryDispatcher {
 
 struct WryMessage(wry::Message<wry::WindowId, Event>);
 
-impl From<(wry::WindowId, Message)> for WryMessage {
-  fn from((id, message): (wry::WindowId, Message)) -> Self {
+impl TryFrom<(wry::WindowId, Message)> for WryMessage {
+  type Error = crate::Error;
+  fn try_from((id, message): (wry::WindowId, Message)) -> crate::Result<Self> {
     let message = match message {
       Message::EvalScript(js) => wry::Message::Webview(id, WebviewMessage::EvalScript(js)),
-      Message::SetWindowTitle(title) => wry::Message::Window(id, WindowMessage::SetTitle(title)),
       Message::Event(event) => wry::Message::Custom(event),
+      Message::SetResizable(resizable) => {
+        wry::Message::Window(id, WindowMessage::SetResizable(resizable))
+      }
+      Message::SetTitle(title) => wry::Message::Window(id, WindowMessage::SetTitle(title)),
+      Message::Maximize => wry::Message::Window(id, WindowMessage::Maximize),
+      Message::Unmaximize => wry::Message::Window(id, WindowMessage::Unmaximize),
+      Message::Minimize => wry::Message::Window(id, WindowMessage::Minimize),
+      Message::Unminimize => wry::Message::Window(id, WindowMessage::Unminimize),
+      Message::Show => wry::Message::Window(id, WindowMessage::Show),
+      Message::Hide => wry::Message::Window(id, WindowMessage::Hide),
+      Message::SetTransparent(transparent) => {
+        wry::Message::Window(id, WindowMessage::SetTransparent(transparent))
+      }
+      Message::SetDecorations(decorations) => {
+        wry::Message::Window(id, WindowMessage::SetDecorations(decorations))
+      }
+      Message::SetAlwaysOnTop(always_on_top) => {
+        wry::Message::Window(id, WindowMessage::SetAlwaysOnTop(always_on_top))
+      }
+      Message::SetWidth(width) => wry::Message::Window(id, WindowMessage::SetWidth(width)),
+      Message::SetHeight(height) => wry::Message::Window(id, WindowMessage::SetHeight(height)),
+      Message::Resize { width, height } => {
+        wry::Message::Window(id, WindowMessage::Resize { width, height })
+      }
+      Message::SetMinSize {
+        min_width,
+        min_height,
+      } => wry::Message::Window(
+        id,
+        WindowMessage::SetMinSize {
+          min_width,
+          min_height,
+        },
+      ),
+      Message::SetMaxSize {
+        max_width,
+        max_height,
+      } => wry::Message::Window(
+        id,
+        WindowMessage::SetMaxSize {
+          max_width,
+          max_height,
+        },
+      ),
+      Message::SetX(x) => wry::Message::Window(id, WindowMessage::SetX(x)),
+      Message::SetY(y) => wry::Message::Window(id, WindowMessage::SetY(y)),
+      Message::SetPosition { x, y } => {
+        wry::Message::Window(id, WindowMessage::SetPosition { x, y })
+      }
+      Message::SetFullscreen(fullscreen) => {
+        wry::Message::Window(id, WindowMessage::SetFullscreen(fullscreen))
+      }
+      Message::SetIcon(icon) => wry::Message::Window(id, WindowMessage::SetIcon(icon.try_into()?)),
     };
-    WryMessage(message)
+    Ok(WryMessage(message))
   }
 }
 
 impl ApplicationDispatcherExt for WryDispatcher {
   fn send_message(&self, message: Message) {
-    let message: WryMessage = (self.current_window, message).into();
-    self
-      .inner
-      .lock()
-      .unwrap()
-      .dispatch_message(message.0)
-      .unwrap();
+    let message_res: crate::Result<WryMessage> = (self.current_window, message).try_into();
+    // TODO error propagation
+    if let Ok(message) = message_res {
+      self
+        .inner
+        .lock()
+        .unwrap()
+        .dispatch_message(message.0)
+        .unwrap();
+    }
   }
 }
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác