Skip to content

feat(mobile): multi-window support#14484

Merged
FabianLars merged 41 commits into
devfrom
feat/mobile-multi-window
Mar 23, 2026
Merged

feat(mobile): multi-window support#14484
FabianLars merged 41 commits into
devfrom
feat/mobile-multi-window

Conversation

@lucasfernog

Copy link
Copy Markdown
Member

Leverages scenes on iOS and Activity embedding on Android.

All window APIs are now exposed on mobile too. Some of them are still ignored though (like setting a title).

iOS

  • Added RunEvent::SceneRequested (on iPad the user can request a new window to be open - e.g. by long pressing the app icon and selecting "New window")

Android

  • Added builder methods to determine the activity to be created. System determines what to do with the activity (new stack, next to another one.. based on the embedding rules)

needs tauri-apps/tao#1154 and tauri-apps/wry#1633

@lucasfernog
lucasfernog requested a review from a team as a code owner November 17, 2025 11:50
@github-actions

github-actions Bot commented Nov 17, 2025

Copy link
Copy Markdown
Contributor

Package Changes Through 865dced

There are 9 changes which include tauri-macos-sign with patch, tauri-build with patch, tauri with minor, tauri-bundler with patch, tauri-cli with patch, @tauri-apps/cli with patch, tauri-runtime-wry with minor, tauri-runtime with minor, tauri-utils with minor

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
tauri-utils 2.8.3 2.9.0
tauri-macos-sign 2.3.3 2.3.4
tauri-bundler 2.8.1 2.8.2
tauri-runtime 2.10.1 2.11.0
tauri-runtime-wry 2.10.1 2.11.0
tauri-codegen 2.5.5 2.5.6
tauri-macros 2.5.5 2.5.6
tauri-plugin 2.5.4 2.5.5
tauri-build 2.5.6 2.5.7
tauri 2.10.3 2.11.0
@tauri-apps/cli 2.10.1 2.10.2
tauri-cli 2.10.1 2.10.2

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

@lucasfernog

Copy link
Copy Markdown
Member Author

@velocitysystems velocitysystems left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're very excited about this feature @lucasfernog. I've left comments on #1154 and #1633. Here are some additional general questions:

Platforms & Compatibility

  • How will this affect Tauri's minimum supported versions?(i.e. Requires iOS 13+ and Android 12L)
  • What is the fallback behavior for unsupported platforms?
  • Which features of the Window API are available vs not available on mobile?

Performance & Resource Management

  • How do we intend to handle app lifecycle events? e.g. sleep/resume
  • How can we optimize multi-window support so as not to affect battery life?


#[cfg(feature = "unstable")]
#[command(root = "crate")]
pub async fn create_webview<R: Runtime>(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we may not wish to enforce this (since it is device-specific) there is a theoretical limit to the number of web-views which can be created based on the available memory.

If the app begins to use too much memory the OS may mark it for termination particularly if it doesn't respond to memory warnings and attempt to free memory.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, that's not something we're worried - otherwise we would need to implement such check for all platforms


#[cfg(feature = "unstable")]
#[command(root = "crate")]
pub async fn create_webview<R: Runtime>(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WebViews are full browser engines that continue consuming significant CPU, GPU, and battery resources (15-25% per hour) even when the app is backgrounded, unless explicitly paused through lifecycle event handlers (onPause/onResume on Android or scene lifecycle hooks on iOS).

This can reduce background drain to 1-3% per hour—a critical requirement for app store approval and acceptable user experience.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for Android the system pauses the activity automatically when it moves to the background.. I would expect iOS to do the same

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lucasfernog Unlike iOS I don't believe Android automatically pauses the WebView's internal threads or JS timers when the Activity's onPause(..) is called. The Android WebView has explicit methods onPause(..) and pauseTimer(..).

See this SO discussion for further discussion.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented that but it didn't help much tauri-apps/wry@0904dc9 (#1633)
i think pauseTimer is something that each user should decide if they want to call or not - they can do so in their TauriActivity subclass.

}

#[cfg(desktop)]
mod desktop_commands {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apps can't currently detect if multi-window is available. Should we add an API like this? e.g.

Typescript

if (await app.supportsMultiWindow()) {
    // Create new window
} else {
    // Ignore
}

Rust

pub fn supports_multi_window() -> bool {
    #[cfg(target_os = "iOS")]
    {
        ios_version() >= 13.0
    }
    #[cfg(target_os = "android")]
    {
        android_api_level() >= 32 // Android 12L
    }
    #[cfg(desktop)]
    {
        true
    }
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea 7f02cf5

@velocitysystems

Copy link
Copy Markdown
Contributor

Would the approach used in this series of PRs also be suitable for having (potentially mutliple) Tauri view's embedded within a single native view hierarchy? e.g. Using things like iOS/Android native bottom tabs, bottom sheets, or stack navigation views and having Tauri/Wry views within those.

The current implementation doesn't support embedding Tauri/Wry views within native view hierarchies like tabs, bottom sheets, or navigation stacks. That would require a different architectural approach at the TAO and WRY layers. This PR enables multiple independent full-screen windows, each with their own webview.

It's worth noting that Tauri's mobile architecture is webview-centric more broadly — there's currently no supported way to embed native UI components alongside the webview. Plugins can access native platform APIs (Swift/Kotlin), but not modify the view hierarchy. There's some discussion around this in #10993.

@FabianLars
FabianLars merged commit 093e2b4 into dev Mar 23, 2026
36 of 37 checks passed
@FabianLars
FabianLars deleted the feat/mobile-multi-window branch March 23, 2026 16:32
lucasfernog added a commit to tauri-apps/tauri-docs that referenced this pull request Apr 14, 2026
razein97 pushed a commit to razein97/tauri that referenced this pull request Apr 30, 2026
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
razein97 pushed a commit to razein97/tauri that referenced this pull request Apr 30, 2026
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
lucasfernog added a commit that referenced this pull request May 4, 2026
… (#15336)

* fix(core): requestPermission crash regression on Android, closes #15323

regression from #14484

PluginManager::onActivityCreate is never called, this fixes it

* tag

* super
import java.lang.reflect.InvocationTargetException

class PluginManager(val activity: AppCompatActivity) {
object PluginManager {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lucasfernog this seems to cause #15506, do we have a reason for the change from class to object here?

Just a note that since we have android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" in the template manifest, the activity should not normally get recreated, but this is still a problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants