Skip to content

fix(tauri): use CSS pixels for embedded window rect - #527

Open
Clarkkkk wants to merge 3 commits into
webdriverio:mainfrom
Clarkkkk:codex/fix-tauri-window-rect-hidpi
Open

fix(tauri): use CSS pixels for embedded window rect#527
Clarkkkk wants to merge 3 commits into
webdriverio:mainfrom
Clarkkkk:codex/fix-tauri-window-rect-hidpi

Conversation

@Clarkkkk

@Clarkkkk Clarkkkk commented Jul 14, 2026

Copy link
Copy Markdown

Description

Fixes the embedded Tauri WebDriver server's desktop Get Window Rect and Set Window Rect implementation so the W3C values are expressed in CSS/logical pixels instead of Tauri physical pixels.

On a Retina display, the existing implementation returned and accepted physical dimensions. A Tauri window reported by WebDriver as 1320x860 at DPR 2 therefore exposed only a 660x430 DOM viewport, and setting a WebDriver size could shrink the application to half of the requested logical size.

This change:

  • converts Tauri physical outer position and size through to_logical() using the current window scale factor;
  • uses LogicalPosition and LogicalSize when applying WebDriver rects;
  • measures the window decoration in logical pixels before a possible display move, avoiding stale physical metrics being combined with a new display scale factor;
  • waits for Tauri's tauri://move and tauri://resize events instead of relying on fixed delays, and reports a WebDriver unknown error if a native operation fails. A window manager may clamp or ignore a request, so an unobserved event is logged and the resulting rect is returned rather than failing the command; the same wait now also covers maximize and fullscreen;
  • applies position before size when both are requested and skips native setters whose requested value is unchanged;
  • documents the CSS-pixel contract without changing the endpoint or public response shape.

The behavior follows the W3C Set Window Rect command and Tauri's PhysicalSize::to_logical API.

Regression evidence

The embedded E2E was first run against the previous implementation. It failed while the existing window tests passed:

should return the native outer rect in logical pixels
Received difference: 2492px

should set the outer size in logical pixels without shrinking the viewport
Received difference: 360px

With the fix, the same Retina run observed a 720x540 WebDriver rect backed by 1440x1080 physical bounds at scale factor 2. The DOM viewport changed by the same logical delta, and all 14 window tests passed.

Related Issues

None.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code style/refactoring (no functional changes)
  • Internal/tooling change (build scripts, CI, etc.)
  • Performance improvement

Scope

  • scope:electron - Electron service and CDP bridge
  • scope:tauri - Tauri service and plugin

Checklist

  • I have read the CONTRIBUTING guidelines
  • My code follows the code style of this project (passes pnpm lint)
  • I have added tests that prove my fix is effective
  • All new and existing tests pass (pnpm test)
  • I have updated the documentation
  • My changes generate no new TypeScript errors (pnpm typecheck)

A direct root pnpm test is not a CI-equivalent entry point on macOS: it bypasses test-package.ts, selects the official Tauri driver fixture, and fails because that provider is unsupported on macOS. The CI-equivalent unit/integration suite, repository pre-push package suite, and the relevant native E2E all pass locally. CI remains responsible for the fully provisioned cross-platform fixture and provider matrix.

Testing

  • Unit tests added/updated
  • Integration tests added/updated (not applicable)
  • E2E tests added/updated
  • Manually tested on: macOS arm64, Retina scale factor 2

Passed locally:

  • cargo test (17 passed)
  • rustfmt --edition 2021 --check src/platform/executor.rs
  • cargo clippy --all-targets -- -D warnings -A clippy::incompatible-msrv
  • pnpm exec turbo run build --filter='./fixtures/package-tests/*' (27 successful)
  • pnpm run test:unit test:integration --only --concurrency=1 (19 successful)
  • pnpm run test:coverage --concurrency=1 (29 successful)
  • TAURI_WEBDRIVER_PORT=4545 pnpm --filter @repo/e2e test:e2e:tauri-basic-embedded:window (14 passing)
  • pnpm format:check
  • pnpm lint
  • pnpm typecheck (28 successful)
  • repository pre-push package suite (26 successful)

Two strict Rust checks expose unrelated current-main/toolchain issues:

  • cargo fmt --check with rustfmt 1.96 reports formatting drift only in untouched Rust files; the modified Rust file passes a direct rustfmt check.
  • cargo clippy --all-targets -- -D warnings with Rust 1.96 reports existing clippy::incompatible_msrv warnings for cast_unsigned / cast_signed because the crate declares MSRV 1.77; allowing only that lint produces a clean clippy run.

Screenshots/Videos

Not applicable; the regression is asserted against WebDriver rects, DOM viewport dimensions, and native Tauri physical bounds.

Additional Context

This changes desktop behavior on macOS, Windows, and Linux because all three platforms share the same cfg(desktop) implementation. Mobile implementations and public endpoint shapes are unchanged. Clients that relied on the non-standard physical-pixel values will now receive W3C CSS-pixel values.

A genuine mixed-DPI multi-display transition was not available for manual testing. Scale factors 1.0, 1.25, and 2.0, negative positions, integer rounding, decoration conversion, combined move/resize, and size-only updates are covered by deterministic Rust tests and the native embedded E2E; CI provides the remaining platform matrix.


Note: This repository does not backport changes to older versions. All changes target the current main branch.

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jul 14, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: Clarkkkk / name: Aaron_Zhou (b2c9cbf)

@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the embedded Tauri WebDriver server's Get Window Rect and Set Window Rect commands to return and accept CSS/logical pixels instead of Tauri physical pixels, which is required by the W3C WebDriver spec. The fix addresses a doubling/halving error on Retina displays (DPR 2) and replaces fixed sleep delays with event-based waiting using Tauri's tauri://move and tauri://resize events.

  • executor.rs: Adds physical_window_rect_to_logical and physical_window_chrome_to_logical helpers; get_window_rect now converts via scale_factor; set_window_rect measures chrome in logical pixels before any display move, skips unchanged native setters, and waits for Tauri events instead of sleeping.
  • window.spec.ts: Adds a new Embedded WebDriver WindowRect CSS pixel semantics describe block with three E2E tests gated to DRIVER_PROVIDER === 'embedded' that cross-validate WebDriver rects against raw native metrics and DOM viewport deltas.
  • main.rs (fixture): Extends get_window_bounds to return a WindowMetrics struct that includes scale_factor, enabling the E2E cross-validation.

Confidence Score: 5/5

Safe to merge; the physical-to-logical conversion is mathematically correct, the Tauri event listener lifecycle is properly managed, and chrome is measured before any display move.

All changed code paths are well-covered by deterministic Rust unit tests and a new E2E suite. Event-based waiting replaces fragile fixed delays without introducing listener leaks. Chrome measurement happens before any position move, avoiding the stale-scale-factor issue from the previous review round. No correctness issues found.

Files Needing Attention: No files require special attention.

Important Files Changed

Filename Overview
packages/tauri-plugin-webdriver/src/platform/executor.rs Core logic change: physical to logical conversion helpers added, get/set_window_rect updated to use scale_factor and event-based waiting; listener lifecycle is handled correctly.
e2e/test/tauri/window.spec.ts New E2E describe block with three logical-pixel semantics tests gated to embedded provider; restores original rect in finally blocks and cross-validates native metrics.
fixtures/e2e-apps/tauri/src-tauri/src/main.rs Adds scale_factor to get_window_bounds response via new WindowMetrics struct; minimal and correct change.
packages/tauri-plugin-webdriver/README.md Documents the CSS-pixel contract for Get/Set Window Rect; accurate and concise.

Reviews (4): Last reviewed commit: "fix(tauri): wait for the resize event on..." | Re-trigger Greptile

Comment thread packages/tauri-plugin-webdriver/src/platform/executor.rs
Comment thread e2e/test/tauri/window.spec.ts Outdated
@Clarkkkk
Clarkkkk marked this pull request as draft July 14, 2026 06:13
@Clarkkkk
Clarkkkk force-pushed the codex/fix-tauri-window-rect-hidpi branch from 2d68e18 to b2c9cbf Compare July 14, 2026 08:07
@Clarkkkk
Clarkkkk marked this pull request as ready for review July 14, 2026 08:09
@goosewobbler
goosewobbler force-pushed the codex/fix-tauri-window-rect-hidpi branch from 8eb5acb to 7f2739b Compare August 1, 2026 10:32
@goosewobbler

goosewobbler commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thanks for this — good catch and a well-targeted fix. Worth noting it's broader than HiDPI ergonomics: official and crabnebula already report CSS pixels, so the same assertion produced different numbers depending on driverProvider. Only the embedded provider was out of spec.

I've pushed three things to the branch:

Rebased onto main — a batch of E2E flake fixes landed since you opened this (#549, #552). Clean rebase.

treat an unobserved window change as best-effortapply_window_change returned unknown error when the confirming event didn't arrive within 1s. A window manager can clamp or refuse a request (ask for a size above the display bounds, or below a min-size constraint, and the clamped result can equal the current size), so no tauri://move/tauri://resize ever fires and the command hard-failed where it previously returned the actual rect. Waiting for the event now degrades to a tracing::debug! and falls through to the existing get_window_rect(). A failure of the native call itself is still an error.

wait for the resize event on maximize and fullscreen — follow-through on the helper you added: maximize_window and fullscreen_window were still on let _ = …; sleep(100ms), so they reported a rect read mid-transition (the macOS fullscreen animation alone outlasts 100ms) and swallowed the native error. Both now route through apply_window_change. minimize_window is untouched — it returns no rect, so there's nothing to stabilise.

Verified on the rebased branch: cargo test 17 passed, rustfmt --check clean on executor.rs, clippy clean apart from two pre-existing violations on main.

@goosewobbler

Copy link
Copy Markdown
Contributor

Thanks for this, @Clarkkkk 🙏 A heads-up on the red CI, since it's specific to this PR — not a flake, so a re-run won't clear it.

Failing job: E2E - Tauri [Linux] - window (embedded provider) — red on all 4 attempts of the latest run (30695910793). It's green on main and on every other open PR I checked (#559/#560/#561 + recent main runs), so it's this change hitting the Linux / WebKitGTK embedded path specifically.

(The E2E - Tauri [macOS-ARM] - standalone red on the same run is unrelated — that's the known #540 macOS idle-stall flake.)

Symptoms are inconsistent across attempts:

  • Some attempts hang to the 5-min leg timeout (Timeout reached, continuing the build); the last WebDriver commands before the hang are setWindowRect / switchToWindow.
  • On the attempt where the new WindowRect CSS pixel semantics tests were skipped, the spec actually passed in ~40s — but the provider was still marked failed by a teardown error: Failed to clear mock store: Error: A sessionId is required for this command.

Where I'd start looking:

  • apply_window_change (the window.once(event_name, …) + oneshot + 1 s timeout) together with set/getWindowRect on WebKitGTK. On Linux the native move/resize and its confirming tauri://… event may not behave like macOS/Windows (the event never fires, or the resize wedges the webview/session) — that would explain both the hang and the session/mock-store teardown error.
  • Worth confirming the new WindowRect tests actually execute on the Linux embedded leg — they looked skipped on one attempt, so the DRIVER_PROVIDER gating in beforeEach may be inconsistent there.

Agreed a Tauri fix should support Linux fully, so gating the tests off Linux isn't the answer. Happy to pair on the WebKitGTK window-rect path if it's useful — maintainer edits are on, so I can push to this branch to help if you'd like. 🙂

Clarkkkk and others added 3 commits August 2, 2026 20:36
Set Window Rect is best-effort under W3C: the command applies the request
and returns the resulting rect, it does not require the request be honored.
A window manager can clamp or ignore a move/resize — request a size above
the display bounds or below a min-size constraint and the clamped result
can equal the current one, so no tauri://move or tauri://resize ever fires.
Failing the command there regresses callers that previously got the actual
rect back.

Only a failure of the native call itself stays an error. Waiting for the
confirming event now degrades to a debug log, and set_window_rect falls
through to reporting the rect the window actually ended up with.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CsgeivZCqduTQmWK55zqiT
maximize_window and fullscreen_window slept for a fixed 100ms and then read
the rect, so they reported whatever the window looked like mid-transition —
the macOS fullscreen animation alone outlasts that budget. They also dropped
the native call's error on the floor.

Route both through apply_window_change so they wait for tauri://resize on the
same best-effort terms as set_window_rect, and surface a failure of the native
call itself. minimize_window is left alone: it returns no rect, so there is
nothing to stabilise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CsgeivZCqduTQmWK55zqiT
@goosewobbler
goosewobbler force-pushed the codex/fix-tauri-window-rect-hidpi branch from 7f2739b to f5caf45 Compare August 2, 2026 19:36
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.

2 participants