On Linux systems using GTK, Tauri applications with multiple webviews experience a critical positioning bug where webviews ignore their position and size settings. Instead of being positioned at specified coordinates, all webviews stack vertically in the default layout container.
- Webviews ignore
set_webview_position()andset_webview_size()calls - Multiple webviews stack vertically instead of positioning absolutely
- Works correctly on Windows and macOS, but fails on Linux
- Issue affects all GTK-based Tauri applications using multiwebview feature
- Tauri: v2.x (all versions up to at least v2.9.x)
- tao: v0.33.x and later
- Platform: Linux (GTK-based systems)
The issue stems from GTK's container system and how Tauri manages child webviews:
- GTK Container Behavior: Tauri on Linux uses
gtk::Box(vertical box layout) as the default container for webviews - Automatic Layout:
gtk::Boxautomatically manages child widget positioning, overriding any manual position settings - Missing Absolute Positioning: GTK requires
gtk::Fixedcontainer for absolute positioning of child widgets - API Gap: The
taowindowing library didn't expose thegtk::Fixedcontainer to Tauri
// PROBLEM: Using gtk::Box (automatic layout)
let vbox = window.default_vbox().unwrap();
webview_builder.build_gtk(vbox)
// GTK's Box widget ignores absolute positioning
// SOLUTION: Using gtk::Fixed (absolute positioning)
let fixed = window.fixed().unwrap();
webview_builder.build_gtk(fixed)
// GTK's Fixed widget respects absolute positioningThe fix requires coordinated changes across two libraries:
Repository: https://github.com/Benjaminlooi/tao
Branch: multiwebview-fix
Changes:
- Add
fixed: Option<gtk::Fixed>field toWindowstruct - Create
gtk::Fixedcontainer during window initialization - Expose
fixed()method inWindowExtUnixtrait API
Modified Files:
src/platform/unix.rs- Added public APIsrc/platform_impl/linux/window.rs- Implementation
Code Changes:
// src/platform/unix.rs
pub trait WindowExtUnix {
// ... existing methods ...
fn fixed(&self) -> Option<>k::Fixed>;
}
impl WindowExtUnix for Window {
fn fixed(&self) -> Option<>k::Fixed> {
self.window.fixed.as_ref()
}
}// src/platform_impl/linux/window.rs
pub struct Window {
pub(crate) window: gtk::ApplicationWindow,
pub(crate) default_vbox: Option<gtk::Box>,
pub(crate) fixed: Option<gtk::Fixed>, // NEW FIELD
// ... other fields ...
}
// During window creation:
let fixed = match default_vbox {
Some(ref vbox) => {
let fixed = gtk::Fixed::new();
vbox.pack_start(&fixed, true, true, 0);
fixed.show_all();
Some(fixed)
},
None => None,
};Repository: https://github.com/Benjaminlooi/tauri
Branch: multiwebview-fix
Changes:
- Replace
window.default_vbox()withwindow.fixed()in webview creation - Add Cargo.toml patch to use patched tao
Modified Files:
crates/tauri-runtime-wry/src/lib.rs(lines 4763, 4788)crates/tauri-runtime-wry/Cargo.toml
Code Changes:
// crates/tauri-runtime-wry/src/lib.rs
// BEFORE (line 4763):
let vbox = window.default_vbox().unwrap();
webview_builder.build_gtk(vbox)
// AFTER:
let fixed = window.fixed().unwrap();
webview_builder.build_gtk(fixed)
// Same change on line 4788# crates/tauri-runtime-wry/Cargo.toml
[patch.crates-io]
tao = { git = "https://github.com/Benjaminlooi/tao.git", branch = "multiwebview-fix" }Add the following to your Cargo.toml:
# Git patches for Linux multiwebview positioning fix
# See: https://github.com/tauri-apps/tauri/issues/10420
[patch.crates-io]
tao = { git = "https://github.com/Benjaminlooi/tao.git" }
tauri-runtime = { git = "https://github.com/Benjaminlooi/tauri.git" }
tauri-runtime-wry = { git = "https://github.com/Benjaminlooi/tauri.git" }
tauri-utils = { git = "https://github.com/Benjaminlooi/tauri.git" }Note: The patches track the default branch and will stay compatible with your Tauri version's dependency requirements.
# Update to use patched versions
cargo update -p tao -p tauri-runtime -p tauri-runtime-wry -p tauri-utils
# Verify patches are applied
cargo tree -p tao --depth 0
cargo tree -p tauri-runtime-wry --depth 0You should see output like:
tao v0.33.0 (https://github.com/Benjaminlooi/tao.git#...)
tauri-runtime-wry v2.6.0 (https://github.com/Benjaminlooi/tauri.git#...)
# Clean build to ensure patches are applied
cargo clean
cargo build
# Or run development server
npm run tauri dev- Create Multiple Webviews: Create 2-3 webviews with different positions
- Set Explicit Positions: Use
set_webview_position()with distinct coordinates - Verify Layout: Webviews should appear at specified positions, not stacked vertically
Before Fix:
┌─────────────────┐
│ Webview 1 │
├─────────────────┤
│ Webview 2 │ <- All stacked vertically
├─────────────────┤
│ Webview 3 │
└─────────────────┘
After Fix:
┌─────────────────────────┐
│ ┌────┐ ┌────┐ │
│ │ W1 │ │ W2 │ │ <- Positioned as specified
│ └────┘ └────┘ │
│ ┌────┐ │
│ │ W3 │ │
│ └────┘ │
└─────────────────────────┘
| Component | Version | Status |
|---|---|---|
| tauri | 2.5.1 | ✅ Working |
| tao | 0.33.0 | ✅ Patched |
| tauri-runtime-wry | 2.6.0 | ✅ Patched |
| GTK | 3.24+ | ✅ Compatible |
The patches are maintained on GitHub and should work with future Tauri versions until the fix is merged upstream. Monitor the issue tracker for official releases that include this fix.
Symptom: Cargo warnings about unused patches
warning: Patch `tao v0.33.0` was not used in the crate graph
Solution: Version mismatch. Check your Tauri version's dependency requirements:
cargo tree -i tao
cargo tree -i tauri-runtime-wryUpdate the patch git URLs to match the required versions, or pin your Tauri version.
Symptom: Trait bound errors or missing methods
Solution:
- Clean build directory:
cargo clean - Update dependencies:
cargo update - Verify patches:
cargo tree -p tao
Symptom: Webviews still appear vertically stacked after applying patches
Possible Causes:
- Old build artifacts - Run
cargo clean - Patches not applied - Verify with
cargo tree - Platform-specific code path - Check that your code runs the GTK path
- Window created with
with_default_vbox(false)- Fix requires default vbox enabled
Symptom: Webviews move to the top-left corner when the main window is resized
Root Cause: Using separate set_position() and set_size() calls doesn't properly trigger GTK Fixed container repositioning
Solution: Use set_bounds() instead, which properly handles GTK Fixed container updates:
// BEFORE (incorrect for GTK Fixed)
webview.set_position(Position::Logical(position))?;
webview.set_size(Size::Logical(size))?;
// AFTER (correct for GTK Fixed)
let bounds = Rect {
position: Position::Logical(position),
size: Size::Logical(size),
};
webview.set_bounds(bounds)?;When the window is resized, the frontend must recalculate webview positions and call set_bounds() to update all webviews. The set_bounds() method internally calls gtk_fixed_move() and properly updates child widget positions within the Fixed container.
Implementation in ChenChen:
- Frontend listens for window resize events (src/routes/+page.svelte:38)
- Debounced handler recalculates panel bounds (src/routes/+page.svelte:86-95)
- Backend command uses
set_bounds()for updates (src-tauri/src/commands.rs:289-291)
The fix has minimal performance impact:
- Memory: One additional
gtk::Fixedwidget per window (~negligible) - CPU: No measurable overhead
- Compatibility: No breaking changes to existing API
If you encounter issues with these patches:
- Bug Reports: Open issues on the respective GitHub repositories
- Improvements: Submit PRs to the patch branches
- Upstream: Encourage Tauri maintainers to merge the fix
- Original Issue: Reported by community members on GitHub issues #10420, #13071
- Fix Implementation: Based on community investigation and GTK documentation
- Patches Maintained By: Benjaminlooi (https://github.com/Benjaminlooi)
- Tauri Issue #10420
- Tauri Issue #13071
- GTK Fixed Container Documentation
- tao Windowing Library
- Patched tao Repository
- Patched tauri Repository
These patches maintain the same license as the original Tauri and tao projects (Apache-2.0/MIT).
Last Updated: 2025-11-19 Tauri Version: 2.9.3 Status: Active patch with resize fix, awaiting upstream merge