Explorar el Código

feat(core): always use child webviews on the unstable feature (#9059)

* feat(core): always use child webviews on the unstable feature

* fmt
Lucas Fernandes Nogueira hace 1 año
padre
commit
46de49aaad

+ 7 - 0
.changes/set-auto-resize.md

@@ -0,0 +1,7 @@
+---
+"tauri": patch:feat
+"tauri-runtime": patch:feat
+"tauri-runtime-wry": patch:feat
+---
+
+Added `set_auto_resize` method for the webview.

+ 6 - 0
.changes/unstable-child-webview.md

@@ -0,0 +1,6 @@
+---
+"tauri": patch:enhance
+"tauri-runtime-wry": patch:enhance
+---
+
+When using the `unstable` feature flag, `WebviewWindow` will internally use the child webview interface for flexibility.

+ 1 - 0
core/tauri-runtime-wry/Cargo.toml

@@ -52,3 +52,4 @@ objc-exception = [ "wry/objc-exception" ]
 linux-protocol-body = [ "wry/linux-body", "webkit2gtk/v2_40" ]
 tracing = [ "dep:tracing", "wry/tracing" ]
 macos-proxy = [ "wry/mac-proxy" ]
+unstable = [ ]

+ 56 - 13
core/tauri-runtime-wry/src/lib.rs

@@ -1174,6 +1174,7 @@ pub enum WebviewMessage {
   SetSize(Size),
   SetFocus,
   Reparent(WindowId),
+  SetAutoResize(bool),
   // Getters
   Url(Sender<Url>),
   Position(Sender<PhysicalPosition<i32>>),
@@ -1384,6 +1385,17 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
     Ok(())
   }
 
+  fn set_auto_resize(&self, auto_resize: bool) -> Result<()> {
+    send_user_message(
+      &self.context,
+      Message::Webview(
+        *self.window_id.lock().unwrap(),
+        self.webview_id,
+        WebviewMessage::SetAutoResize(auto_resize),
+      ),
+    )
+  }
+
   #[cfg(all(feature = "tracing", not(target_os = "android")))]
   fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
     // use a channel so the EvaluateScript task uses the current span as parent
@@ -1883,7 +1895,7 @@ pub struct WebviewWrapper {
   webview_event_listeners: WebviewEventListeners,
   // the key of the WebContext if it's not shared
   context_key: Option<PathBuf>,
-  bounds: Option<Arc<Mutex<WebviewBounds>>>,
+  bounds: Arc<Mutex<Option<WebviewBounds>>>,
 }
 
 impl Deref for WebviewWrapper {
@@ -2824,11 +2836,10 @@ fn handle_user_message<T: UserEvent>(
             bounds.width = size.width;
             bounds.height = size.height;
 
-            if let Some(b) = &webview.bounds {
+            if let Some(b) = &mut *webview.bounds.lock().unwrap() {
               let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
-              let mut bounds = b.lock().unwrap();
-              bounds.width_rate = size.width as f32 / window_size.width;
-              bounds.height_rate = size.height as f32 / window_size.height;
+              b.width_rate = size.width as f32 / window_size.width;
+              b.height_rate = size.height as f32 / window_size.height;
             }
 
             webview.set_bounds(bounds);
@@ -2839,12 +2850,10 @@ fn handle_user_message<T: UserEvent>(
             bounds.x = position.x;
             bounds.y = position.y;
 
-            if let Some(b) = &webview.bounds {
+            if let Some(b) = &mut *webview.bounds.lock().unwrap() {
               let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
-              let mut bounds = b.lock().unwrap();
-
-              bounds.x_rate = position.x as f32 / window_size.width;
-              bounds.y_rate = position.y as f32 / window_size.height;
+              b.x_rate = position.x as f32 / window_size.width;
+              b.y_rate = position.y as f32 / window_size.height;
             }
 
             webview.set_bounds(bounds);
@@ -2868,6 +2877,20 @@ fn handle_user_message<T: UserEvent>(
           WebviewMessage::SetFocus => {
             webview.focus();
           }
+          WebviewMessage::SetAutoResize(auto_resize) => {
+            let bounds = webview.bounds();
+            let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
+            *webview.bounds.lock().unwrap() = if auto_resize {
+              Some(WebviewBounds {
+                x_rate: (bounds.x as f32) / window_size.width,
+                y_rate: (bounds.y as f32) / window_size.height,
+                width_rate: (bounds.width as f32) / window_size.width,
+                height_rate: (bounds.height as f32) / window_size.height,
+              })
+            } else {
+              None
+            };
+          }
           WebviewMessage::WithWebview(f) => {
             #[cfg(any(
               target_os = "linux",
@@ -3186,8 +3209,7 @@ fn handle_event_loop<T: UserEvent>(
             {
               let size = size.to_logical::<f32>(window.scale_factor());
               for webview in webviews {
-                if let Some(bounds) = &webview.bounds {
-                  let b = bounds.lock().unwrap();
+                if let Some(b) = &*webview.bounds.lock().unwrap() {
                   webview.set_bounds(wry::Rect {
                     x: (size.width * b.x_rate) as i32,
                     y: (size.height * b.y_rate) as i32,
@@ -3427,6 +3449,9 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
 
   if let Some(webview) = webview {
     webviews.push(create_webview(
+      #[cfg(feature = "unstable")]
+      WebviewKind::WindowChild,
+      #[cfg(not(feature = "unstable"))]
       WebviewKind::WindowContent,
       &window,
       Arc::new(Mutex::new(window_id)),
@@ -3622,6 +3647,24 @@ fn create_webview<T: UserEvent>(
       None
     }
   } else {
+    #[cfg(feature = "unstable")]
+    {
+      let window_size = window.inner_size().to_logical::<u32>(window.scale_factor());
+
+      webview_builder = webview_builder.with_bounds(wry::Rect {
+        x: 0,
+        y: 0,
+        width: window_size.width,
+        height: window_size.height,
+      });
+      Some(WebviewBounds {
+        x_rate: 0.,
+        y_rate: 0.,
+        width_rate: 1.,
+        height_rate: 1.,
+      })
+    }
+    #[cfg(not(feature = "unstable"))]
     None
   };
 
@@ -3829,7 +3872,7 @@ fn create_webview<T: UserEvent>(
     } else {
       web_context_key
     },
-    bounds: webview_bounds.map(|b| Arc::new(Mutex::new(b))),
+    bounds: Arc::new(Mutex::new(webview_bounds)),
   })
 }
 

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

@@ -452,6 +452,9 @@ pub trait WebviewDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + '
 
   /// Moves the webview to the given window.
   fn reparent(&self, window_id: WindowId) -> Result<()>;
+
+  /// Sets whether the webview should automatically grow and shrink its size and position when the parent window resizes.
+  fn set_auto_resize(&self, auto_resize: bool) -> Result<()>;
 }
 
 /// Window dispatcher. A thread-safe handle to the window APIs.

+ 1 - 1
core/tauri/Cargo.toml

@@ -126,7 +126,7 @@ http-range = "0.1.5"
 
 [features]
 default = [ "wry", "compression", "objc-exception", "common-controls-v6" ]
-unstable = [ ]
+unstable = [ "tauri-runtime-wry/unstable" ]
 common-controls-v6 = [ "tray-icon?/common-controls-v6", "muda/common-controls-v6" ]
 tray-icon = [ "dep:tray-icon" ]
 tracing = [

+ 0 - 2
core/tauri/src/manager/window.rs

@@ -77,7 +77,6 @@ impl<R: Runtime> WindowManager<R> {
     &self,
     app_handle: AppHandle<R>,
     window: DetachedWindow<EventLoopMessage, R>,
-    is_webview_window: bool,
     #[cfg(desktop)] menu: Option<crate::window::WindowMenu<R>>,
   ) -> Window<R> {
     let window = Window::new(
@@ -86,7 +85,6 @@ impl<R: Runtime> WindowManager<R> {
       app_handle,
       #[cfg(desktop)]
       menu,
-      is_webview_window,
     );
 
     let window_ = window.clone();

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

@@ -544,6 +544,10 @@ impl<T: UserEvent> WebviewDispatch<T> for MockWebviewDispatcher {
   fn reparent(&self, window_id: WindowId) -> Result<()> {
     Ok(())
   }
+
+  fn set_auto_resize(&self, auto_resize: bool) -> Result<()> {
+    Ok(())
+  }
 }
 
 impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {

+ 34 - 47
core/tauri/src/webview/mod.rs

@@ -896,42 +896,27 @@ impl<R: Runtime> Webview<R> {
 
   /// Closes this webview.
   pub fn close(&self) -> crate::Result<()> {
-    let window = self.window();
-    if window.is_webview_window() {
-      window.close()
-    } else {
-      self.webview.dispatcher.close()?;
-      self.manager().on_webview_close(self.label());
-      Ok(())
-    }
+    self.webview.dispatcher.close()?;
+    self.manager().on_webview_close(self.label());
+    Ok(())
   }
 
   /// Resizes this webview.
   pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
-    let window = self.window();
-    if window.is_webview_window() {
-      window.set_size(size.into())
-    } else {
-      self
-        .webview
-        .dispatcher
-        .set_size(size.into())
-        .map_err(Into::into)
-    }
+    self
+      .webview
+      .dispatcher
+      .set_size(size.into())
+      .map_err(Into::into)
   }
 
   /// Sets this webviews's position.
   pub fn set_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
-    let window = self.window();
-    if window.is_webview_window() {
-      window.set_position(position.into())
-    } else {
-      self
-        .webview
-        .dispatcher
-        .set_position(position.into())
-        .map_err(Into::into)
-    }
+    self
+      .webview
+      .dispatcher
+      .set_position(position.into())
+      .map_err(Into::into)
   }
 
   /// Focus the webview.
@@ -941,14 +926,26 @@ impl<R: Runtime> Webview<R> {
 
   /// Move the webview to the given window.
   pub fn reparent(&self, window: &Window<R>) -> crate::Result<()> {
-    let current_window = self.window();
-    if current_window.is_webview_window() || window.is_webview_window() {
-      Err(crate::Error::CannotReparentWebviewWindow)
-    } else {
-      self.webview.dispatcher.reparent(window.window.id)?;
-      *self.window_label.lock().unwrap() = window.label().to_string();
-      Ok(())
+    #[cfg(not(feature = "unstable"))]
+    {
+      let current_window = self.window();
+      if current_window.is_webview_window() || window.is_webview_window() {
+        return Err(crate::Error::CannotReparentWebviewWindow);
+      }
     }
+
+    self.webview.dispatcher.reparent(window.window.id)?;
+    *self.window_label.lock().unwrap() = window.label().to_string();
+    Ok(())
+  }
+
+  /// Sets whether the webview should automatically grow and shrink its size and position when the parent window resizes.
+  pub fn set_auto_resize(&self, auto_resize: bool) -> crate::Result<()> {
+    self
+      .webview
+      .dispatcher
+      .set_auto_resize(auto_resize)
+      .map_err(Into::into)
   }
 
   /// Returns the webview position.
@@ -956,22 +953,12 @@ impl<R: Runtime> Webview<R> {
   /// - For child webviews, returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the parent window.
   /// - For webview window, returns the inner position of the window.
   pub fn position(&self) -> crate::Result<PhysicalPosition<i32>> {
-    let window = self.window();
-    if window.is_webview_window() {
-      window.inner_position()
-    } else {
-      self.webview.dispatcher.position().map_err(Into::into)
-    }
+    self.webview.dispatcher.position().map_err(Into::into)
   }
 
   /// Returns the physical size of the webviews's client area.
   pub fn size(&self) -> crate::Result<PhysicalSize<u32>> {
-    let window = self.window();
-    if window.is_webview_window() {
-      window.inner_size()
-    } else {
-      self.webview.dispatcher.size().map_err(Into::into)
-    }
+    self.webview.dispatcher.size().map_err(Into::into)
   }
 }
 

+ 1 - 8
core/tauri/src/window/mod.rs

@@ -404,7 +404,6 @@ tauri::Builder::default()
       let window = app_manager.window.attach_window(
         self.manager.app_handle().clone(),
         detached_window.clone(),
-        detached_window.webview.is_some(),
         #[cfg(desktop)]
         window_menu,
       );
@@ -865,8 +864,6 @@ pub struct Window<R: Runtime> {
   // The menu set for this window
   #[cfg(desktop)]
   pub(crate) menu: Arc<std::sync::Mutex<Option<WindowMenu<R>>>>,
-  /// Whether this window is a Webview window (hosts only a single webview) or a container for multiple webviews
-  is_webview_window: bool,
 }
 
 impl<R: Runtime> std::fmt::Debug for Window<R> {
@@ -875,7 +872,6 @@ impl<R: Runtime> std::fmt::Debug for Window<R> {
       .field("window", &self.window)
       .field("manager", &self.manager)
       .field("app_handle", &self.app_handle)
-      .field("is_webview_window", &self.is_webview_window)
       .finish()
   }
 }
@@ -896,7 +892,6 @@ impl<R: Runtime> Clone for Window<R> {
       app_handle: self.app_handle.clone(),
       #[cfg(desktop)]
       menu: self.menu.clone(),
-      is_webview_window: self.is_webview_window,
     }
   }
 }
@@ -951,7 +946,6 @@ impl<R: Runtime> Window<R> {
     window: DetachedWindow<EventLoopMessage, R>,
     app_handle: AppHandle<R>,
     #[cfg(desktop)] menu: Option<WindowMenu<R>>,
-    is_webview_window: bool,
   ) -> Self {
     Self {
       window,
@@ -959,7 +953,6 @@ impl<R: Runtime> Window<R> {
       app_handle,
       #[cfg(desktop)]
       menu: Arc::new(std::sync::Mutex::new(menu)),
-      is_webview_window,
     }
   }
 
@@ -1007,7 +1000,7 @@ impl<R: Runtime> Window<R> {
   }
 
   pub(crate) fn is_webview_window(&self) -> bool {
-    self.is_webview_window
+    self.webviews().iter().all(|w| w.label() == self.label())
   }
 
   /// Runs the given closure on the main thread.