Skip to content

fix(linux): correct browser webview boundaries and positioning using GTK overlays - #398

Merged
gnoviawan merged 5 commits into
gnoviawan:devfrom
muhamadgalihsaputra:fix/linux-webview-bounds
Jul 28, 2026
Merged

fix(linux): correct browser webview boundaries and positioning using GTK overlays#398
gnoviawan merged 5 commits into
gnoviawan:devfrom
muhamadgalihsaputra:fix/linux-webview-bounds

Conversation

@muhamadgalihsaputra

@muhamadgalihsaputra muhamadgalihsaputra commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes browser child webviews appearing below the browser tab on Linux by reparenting them into the main GTK overlay.
  • Keeps renderer-provided bounds in CSS/logical pixels so HiDPI Linux layouts are not double-scaled.
  • Removes the blanket unsafe Send/Sync wrapper around GTK handles.
  • Waits for GTK placement to complete before registering the tab or starting its URL poller, and closes the child webview if placement fails.
  • Removes repeated DOM-height diagnostics from resize handling.

Related Issue

Closes #387

No duplicate pull request addressing this Linux GTK placement bug was found during the original contribution flow.

Type of Change

  • feat: new feature
  • fix: bug fix
  • docs: documentation only
  • style: formatting or non-functional styling changes
  • refactor: internal cleanup with no behavior change
  • perf: performance improvement
  • test: adds or updates tests
  • build: build or dependency changes
  • ci: CI/CD workflow changes
  • chore: maintenance or tooling
  • revert: reverts a previous change

What Changed

  • Added Linux GTK overlay placement using only UI-thread widget access.
  • Made BrowserTabManager::create asynchronous so GTK callback errors are returned through the existing IpcResult contract.
  • Added cleanup for missing-main-webview, callback dispatch, callback cancellation, and GTK hierarchy failures.
  • Removed Linux scale-factor division from browser creation and resize paths.
  • Propagated Linux resize, show, and hide dispatch failures.
  • Removed repeated renderer console/backend diagnostics and added regression coverage for logical bounds.
  • Added the Linux-only GTK dependency required by the native placement implementation.

How It Was Tested

  • bun run ci (Biome lint + format + imports, strict mode)
  • bun run typecheck (GitHub PR Validation: Lint, Typecheck & Test)
  • bun run test (GitHub PR Validation: Lint, Typecheck & Test)
  • cargo clippy --all-targets -- -D warnings (GitHub PR Validation: Rust Checks)
  • cargo test (GitHub PR Validation: Rust Checks)
  • Manual verification completed
  • Not applicable

Focused local validation completed:

  • npx vitest run src/renderer/hooks/use-browser-webview.test.tsx
  • npx biome check src/renderer/hooks/use-browser-webview.ts src/renderer/hooks/use-browser-webview.test.tsx
  • cargo check --manifest-path src-tauri/Cargo.toml --all-targets

GitHub validation also passed the Windows Rust smoke check, standalone server build, web/Tauri frontend builds, CodeQL, dependency review, and secret scan.

Screenshots or Recordings

Existing reproduction screenshots are available in #387. The automated Linux Rust/build gates pass; no Linux desktop runtime was available for a new recording.

CI & Review Gate

  • All CI checks pass (PR Validation, Rust Checks, Build Verification, Security Scans)
  • Code review comments from CodeRabbit / Claude have been addressed in the pushed code
  • No unresolved review findings remain

Checklist

  • My PR title follows the conventional commit format used by this repo
  • I linked the related issue or explained why none exists
  • I updated docs when needed (no user-facing documentation change required)
  • I added or updated tests when needed
  • I verified the change does not introduce unrelated modifications
  • I read AGENTS.md and followed the contributor guidelines
  • A human reviewed the complete diff before submission

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Browser tab creation is asynchronous and performs Linux GTK overlay placement before recording tab state. Resize, visibility, and destruction update native child widgets. Renderer tests cover deterministic bounds updates and listener cleanup.

Changes

Browser webview placement

Layer / File(s) Summary
Async Linux tab creation
src-tauri/Cargo.toml, src-tauri/src/browser_tab_manager.rs, src-tauri/src/commands.rs
Adds the Linux GTK dependency, makes tab creation asynchronous, reparents child webviews into overlays, and awaits creation from the command.
Linux lifecycle updates
src-tauri/src/browser_tab_manager.rs
Updates native widget bounds and visibility on Linux and removes widgets from overlays during destruction.
Renderer lifecycle validation
src/renderer/hooks/use-browser-webview.test.tsx, src/renderer/layouts/WorkspaceLayout.test.tsx
Adds deterministic resize and bounds assertions and extends the Tauri runtime mock with listener cleanup behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BrowserTabCreate
  participant BrowserTabManager
  participant MainWebview
  participant GTKOverlay
  BrowserTabCreate->>BrowserTabManager: await create(tab_id, url, bounds)
  BrowserTabManager->>MainWebview: dispatch GTK placement with with_webview
  MainWebview->>GTKOverlay: add child widget and set bounds
  GTKOverlay-->>BrowserTabManager: placement completes
  BrowserTabManager-->>BrowserTabCreate: return BrowserTabInfo
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #387 by reparenting the browser webview into the correct GTK tab area and preserving bounds on Linux.
Out of Scope Changes check ✅ Passed The added dependency and tests support the Linux webview fix and do not introduce unrelated changes.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the Linux GTK overlay reparenting and browser webview positioning fixes in this PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/browser_tab_manager.rs`:
- Around line 5-7: The blanket SendWrapper<T> unsafe impls are making all GTK
handles look thread-safe, but it is only used to pass main_widget into the
nested Linux with_webview path in BrowserTabManager::create. Remove
SendWrapper<T> and change the handoff so the GTK widget stays on the main
thread, or use a type-specific mechanism that does not require marking arbitrary
T as Send/Sync.
- Around line 230-297: The Linux GTK reparent path in
`BrowserTabManager::create` is swallowing failures by only logging inside
`handle_reparent()` and then continuing as if the tab was created successfully.
Update the `create()` flow so that a reparent failure from the
`main_webview`/`child_webview` setup is propagated back to the caller instead of
starting the poller, inserting the tab, and returning `Ok`. Use the existing
`handle_reparent` result and the surrounding `with_webview`/`create` logic to
return the error when reparenting fails.
- Around line 206-215: `BrowserBounds` is being converted twice on Linux by
dividing `bounds` by `scale_factor`, which breaks logical-pixel coordinates from
`getBoundingClientRect()`. Update the Linux handling in the browser tab bounds
path to keep `x`, `y`, `w`, and `h` in CSS/logical pixels end-to-end, and remove
the extra `scale_factor` division in this block. Also apply the same
logical-pixel treatment to the other Linux-specific bounds conversion paths in
`browser_tab_manager.rs` so all Tauri/GTK webview placement uses consistent
units.

In `@src/renderer/hooks/use-browser-webview.ts`:
- Line 1: The DOM-height diagnostics in use-browser-webview are too chatty
because updateBounds runs on ResizeObserver and visibility changes, causing
repeated console output and WARN IPCs before the webview exists. Update the
updateBounds flow in use-browser-webview to gate this logging to a one-shot or
dev-only path, and route any frontend error reporting through the existing
logFrontendError wrapper instead of direct console/IPC spam. Keep the fix
localized around the updateBounds logic and the webview creation/visibility
checks so split-layout resizes do not flood logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 51d1d91e-bba0-4610-b2f7-68b7a6ada7b6

📥 Commits

Reviewing files that changed from the base of the PR and between 83d3aac and a4270eb.

📒 Files selected for processing (2)
  • src-tauri/src/browser_tab_manager.rs
  • src/renderer/hooks/use-browser-webview.ts

Comment thread src-tauri/src/browser_tab_manager.rs Outdated
Comment thread src-tauri/src/browser_tab_manager.rs Outdated
Comment thread src-tauri/src/browser_tab_manager.rs Outdated
Comment thread src/renderer/hooks/use-browser-webview.ts Outdated
@gnoviawan
gnoviawan force-pushed the fix/linux-webview-bounds branch from 3f9b0a2 to 482fdf6 Compare July 28, 2026 06:16

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src-tauri/src/commands.rs (1)

207-212: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Enforce the attachment cap while reading.

The metadata check is point-in-time; a file that grows after the check is still read with read_to_end, which can exceed the 10 MB cap before the post-read rejection. Read at most ATTACHMENT_MAX_IMAGE_BYTES + 1 bytes before returning the result.

Proposed fix
-    file.read_to_end(&mut bytes)
+    file.take(ATTACHMENT_MAX_IMAGE_BYTES + 1)
+        .read_to_end(&mut bytes)
         .map_err(|e| format!("Failed to read attachment: {}", e))?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/commands.rs` around lines 207 - 212, Update the attachment read
flow around the existing file.read_to_end call to cap bytes read at
ATTACHMENT_MAX_IMAGE_BYTES + 1, then retain the bytes.len() check so oversized
attachments return the existing 10 MB limit error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/browser_tab_manager.rs`:
- Around line 541-545: Update the Linux GTK branches of the generic show() and
hide() methods to propagate errors returned by with_webview, matching the
existing error-handling pattern in resize(). Remove the discarded-result
bindings and return or otherwise forward the dispatch failure so show() and
hide() cannot report success when the child widget update fails.

---

Outside diff comments:
In `@src-tauri/src/commands.rs`:
- Around line 207-212: Update the attachment read flow around the existing
file.read_to_end call to cap bytes read at ATTACHMENT_MAX_IMAGE_BYTES + 1, then
retain the bytes.len() check so oversized attachments return the existing 10 MB
limit error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 87207cd2-9cfb-4fdc-8193-1a3b46eb8bdd

📥 Commits

Reviewing files that changed from the base of the PR and between a4270eb and 3e91976.

📒 Files selected for processing (5)
  • src-tauri/Cargo.toml
  • src-tauri/src/browser_tab_manager.rs
  • src-tauri/src/commands.rs
  • src/renderer/hooks/use-browser-webview.test.tsx
  • src/renderer/layouts/WorkspaceLayout.test.tsx

Comment thread src-tauri/src/browser_tab_manager.rs Outdated
@gnoviawan
gnoviawan force-pushed the fix/linux-webview-bounds branch from 9cd97e3 to ebcdb9a Compare July 28, 2026 06:34
@gnoviawan
gnoviawan merged commit 5393b42 into gnoviawan:dev Jul 28, 2026
25 checks passed
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.

Browser: not showing inside tab

2 participants