Skip to content

Commit

Permalink
feat(core): always use child webviews on the unstable feature (#9059)
Browse files Browse the repository at this point in the history
* feat(core): always use child webviews on the unstable feature

* fmt
  • Loading branch information
lucasfernog authored Mar 4, 2024
1 parent b4ffbe7 commit 46de49a
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 71 deletions.
7 changes: 7 additions & 0 deletions .changes/set-auto-resize.md
Original file line number Diff line number Diff line change
@@ -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 changes: 6 additions & 0 deletions .changes/unstable-child-webview.md
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions core/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [ ]
69 changes: 56 additions & 13 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,7 @@ pub enum WebviewMessage {
SetSize(Size),
SetFocus,
Reparent(WindowId),
SetAutoResize(bool),
// Getters
Url(Sender<Url>),
Position(Sender<PhysicalPosition<i32>>),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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",
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -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
};

Expand Down Expand Up @@ -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)),
})
}

Expand Down
3 changes: 3 additions & 0 deletions core/tauri-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
2 changes: 0 additions & 2 deletions core/tauri/src/manager/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -86,7 +85,6 @@ impl<R: Runtime> WindowManager<R> {
app_handle,
#[cfg(desktop)]
menu,
is_webview_window,
);

let window_ = window.clone();
Expand Down
4 changes: 4 additions & 0 deletions core/tauri/src/test/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
81 changes: 34 additions & 47 deletions core/tauri/src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -941,37 +926,39 @@ 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.
///
/// - 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)
}
}

Expand Down
9 changes: 1 addition & 8 deletions core/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
Expand Down Expand Up @@ -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> {
Expand All @@ -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()
}
}
Expand All @@ -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,
}
}
}
Expand Down Expand Up @@ -951,15 +946,13 @@ 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,
manager,
app_handle,
#[cfg(desktop)]
menu: Arc::new(std::sync::Mutex::new(menu)),
is_webview_window,
}
}

Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 46de49a

Please sign in to comment.