Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix webview not focused by default #11569

Merged
merged 5 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/webview-focus-apis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": "patch:feat"
---

Add `WebviewBuilder::focused` method to choose whether to focus webview or not on creation.
7 changes: 7 additions & 0 deletions .changes/webview-window-focused.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tauri": "patch:bug"
"tauri-runtime": "patch:bug"
"tauri-runtime-wry": "patch:bug"
---

Fix webview not focused by default.
4 changes: 2 additions & 2 deletions crates/tauri-cli/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@
]
},
"Capability": {
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
Expand Down Expand Up @@ -1151,7 +1151,7 @@
}
},
"permissions": {
"description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```",
"description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```",
"type": "array",
"items": {
"$ref": "#/definitions/PermissionEntry"
Expand Down
3 changes: 2 additions & 1 deletion crates/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,7 @@ impl WindowBuilder for WindowBuilderWrapper {
window = window
.title(config.title.to_string())
.inner_size(config.width, config.height)
.focused(config.focus)
.visible(config.visible)
.resizable(config.resizable)
.fullscreen(config.fullscreen)
Expand Down Expand Up @@ -4017,7 +4018,7 @@ fn create_webview<T: UserEvent>(

let mut webview_builder = WebViewBuilder::with_web_context(&mut web_context.inner)
.with_id(&label)
.with_focused(window.is_focused())
.with_focused(webview_attributes.focus)
.with_url(&url)
.with_transparent(webview_attributes.transparent)
.with_accept_first_mouse(webview_attributes.accept_first_mouse)
Expand Down
18 changes: 14 additions & 4 deletions crates/tauri-runtime/src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ pub struct WebviewAttributes {
pub window_effects: Option<WindowEffectsConfig>,
pub incognito: bool,
pub transparent: bool,
pub focus: bool,
pub bounds: Option<Rect>,
pub auto_resize: bool,
pub proxy_url: Option<Url>,
Expand All @@ -213,8 +214,11 @@ pub struct WebviewAttributes {

impl From<&WindowConfig> for WebviewAttributes {
fn from(config: &WindowConfig) -> Self {
let mut builder = Self::new(config.url.clone());
builder = builder.incognito(config.incognito);
let mut builder = Self::new(config.url.clone())
.incognito(config.incognito)
.focused(config.focus)
.zoom_hotkeys_enabled(config.zoom_hotkeys_enabled)
.browser_extensions_enabled(config.browser_extensions_enabled);
#[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
{
builder = builder.transparent(config.transparent);
Expand All @@ -235,8 +239,6 @@ impl From<&WindowConfig> for WebviewAttributes {
if let Some(url) = &config.proxy_url {
builder = builder.proxy_url(url.to_owned());
}
builder = builder.zoom_hotkeys_enabled(config.zoom_hotkeys_enabled);
builder = builder.browser_extensions_enabled(config.browser_extensions_enabled);
builder
}
}
Expand All @@ -256,6 +258,7 @@ impl WebviewAttributes {
window_effects: None,
incognito: false,
transparent: false,
focus: true,
bounds: None,
auto_resize: false,
proxy_url: None,
Expand Down Expand Up @@ -338,6 +341,13 @@ impl WebviewAttributes {
self
}

/// Whether the webview should be focused or not.
#[must_use]
pub fn focused(mut self, focus: bool) -> Self {
self.focus = focus;
self
}

/// Sets the webview to automatically grow and shrink its size and position when the parent window resizes.
#[must_use]
pub fn auto_resize(mut self) -> Self {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Capability",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
Expand Down Expand Up @@ -48,7 +48,7 @@
}
},
"permissions": {
"description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```",
"description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```",
"type": "array",
"items": {
"$ref": "#/definitions/PermissionEntry"
Expand Down
4 changes: 2 additions & 2 deletions crates/tauri-schema-generator/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@
]
},
"Capability": {
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
Expand Down Expand Up @@ -1151,7 +1151,7 @@
}
},
"permissions": {
"description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```",
"description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```",
"type": "array",
"items": {
"$ref": "#/definitions/PermissionEntry"
Expand Down
7 changes: 7 additions & 0 deletions crates/tauri/src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,13 @@ fn main() {
self
}

/// Whether the webview should be focused or not.
#[must_use]
pub fn focused(mut self, focus: bool) -> Self {
self.webview_attributes.focus = focus;
self
}

/// Sets the webview to automatically grow and shrink its size and position when the parent window resizes.
#[must_use]
pub fn auto_resize(mut self) -> Self {
Expand Down
42 changes: 31 additions & 11 deletions crates/tauri/src/webview/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ mod desktop_commands {
WebviewWindowBuilder,
};

fn default_true() -> bool {
true
}

#[derive(Debug, PartialEq, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WebviewConfig {
Expand All @@ -35,6 +39,8 @@ mod desktop_commands {
height: f64,
#[serde(default)]
transparent: bool,
#[serde(default = "default_true")]
focus: bool,
#[serde(default)]
accept_first_mouse: bool,
window_effects: Option<WindowEffectsConfig>,
Expand All @@ -44,6 +50,23 @@ mod desktop_commands {
zoom_hotkeys_enabled: bool,
}

#[cfg(feature = "unstable")]
impl<R: Runtime> crate::webview::WebviewBuilder<R> {
fn from_webview_config(label: String, config: WebviewConfig) -> Self {
let mut builder = Self::new(label, config.url);
builder.webview_attributes.user_agent = config.user_agent;
builder.webview_attributes.drag_drop_handler_enabled =
config.drag_drop_enabled.unwrap_or(true);
builder.webview_attributes.transparent = config.transparent;
builder.webview_attributes.focus = config.focus;
builder.webview_attributes.accept_first_mouse = config.accept_first_mouse;
builder.webview_attributes.window_effects = config.window_effects;
builder.webview_attributes.incognito = config.incognito;
builder.webview_attributes.zoom_hotkeys_enabled = config.zoom_hotkeys_enabled;
builder
}
}

#[derive(Serialize)]
pub struct WebviewRef {
window_label: String,
Expand Down Expand Up @@ -89,21 +112,18 @@ mod desktop_commands {
.manager()
.get_window(&window_label)
.ok_or(crate::Error::WindowNotFound)?;
let mut builder = crate::webview::WebviewBuilder::new(label, options.url);

builder.webview_attributes.user_agent = options.user_agent;
builder.webview_attributes.drag_drop_handler_enabled =
options.drag_drop_enabled.unwrap_or(true);
builder.webview_attributes.transparent = options.transparent;
builder.webview_attributes.accept_first_mouse = options.accept_first_mouse;
builder.webview_attributes.window_effects = options.window_effects;
builder.webview_attributes.incognito = options.incognito;
builder.webview_attributes.zoom_hotkeys_enabled = options.zoom_hotkeys_enabled;
let x = options.x;
let y = options.y;
let width = options.width;
let height = options.height;

let builder = crate::webview::WebviewBuilder::from_webview_config(label, options);

window.add_child(
builder,
tauri_runtime::dpi::LogicalPosition::new(options.x, options.y),
tauri_runtime::dpi::LogicalSize::new(options.width, options.height),
tauri_runtime::dpi::LogicalPosition::new(x, y),
tauri_runtime::dpi::LogicalSize::new(width, height),
)?;

Ok(())
Expand Down
4 changes: 3 additions & 1 deletion crates/tauri/src/webview/webview_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,17 +476,19 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
#[must_use]
#[deprecated(
since = "1.2.0",
note = "The window is automatically focused by default. This function Will be removed in 2.0.0. Use `focused` instead."
note = "The window is automatically focused by default. This function Will be removed in 3.0.0. Use `focused` instead."
)]
pub fn focus(mut self) -> Self {
self.window_builder = self.window_builder.focused(true);
self.webview_builder = self.webview_builder.focused(true);
self
}

/// Whether the window will be initially focused or not.
#[must_use]
pub fn focused(mut self, focused: bool) -> Self {
self.window_builder = self.window_builder.focused(focused);
self.webview_builder = self.webview_builder.focused(focused);
self
}

Expand Down
2 changes: 1 addition & 1 deletion crates/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ impl<'a, R: Runtime, M: Manager<R>> WindowBuilder<'a, R, M> {
#[must_use]
#[deprecated(
since = "1.2.0",
note = "The window is automatically focused by default. This function Will be removed in 2.0.0. Use `focused` instead."
note = "The window is automatically focused by default. This function Will be removed in 3.0.0. Use `focused` instead."
)]
pub fn focus(mut self) -> Self {
self.window_builder = self.window_builder.focused(true);
Expand Down
6 changes: 6 additions & 0 deletions packages/api/src/webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,12 @@ interface WebviewOptions {
* WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.
*/
transparent?: boolean
/**
* Whether the webview should have focus or not
*
* @since 2.1.0
*/
focus?: boolean
/**
* Whether the drag and drop is enabled or not on the webview. By default it is enabled.
*
Expand Down