Description
trafficLightPosition / with_traffic_light_inset positions are not maintained after AppKit layout passes triggered by content view replacement and webview content rendering. The traffic light buttons snap back to default macOS positions.
Root Cause
WryWebViewParent repositions traffic lights only in its drawRect: override (wry_web_view_parent.rs:42-47). drawRect: is a draw-phase method, not a layout-phase method. AppKit can reset button positions during layout passes that occur independently of (and sometimes after) the draw pass.
Specifically:
setContentView: (at wkwebview/mod.rs:664) triggers a titlebar relayout that can reset button positions after set_traffic_light_inset already positioned them correctly at line 653.
- When webview content loads and triggers a content size change, AppKit performs another layout pass that resets button positions.
- If these layout passes don't trigger a subsequent
drawRect: call, the buttons stay at default positions.
This is most visible in production builds where the bundled frontend loads synchronously from the app bundle, causing the content-triggered relayout to happen during initial display before any user interaction triggers a redraw.
Steps to Reproduce
- Create a Tauri v2 app with
titleBarStyle: "Overlay" and trafficLightPosition: { "x": 16, "y": 22 }
- Build a production binary (
tauri build)
- Launch the app
- Observe that traffic light buttons are at the default macOS position, not at (16, 22)
The issue is intermittent and timing-dependent -- it reproduces more reliably in production builds than dev builds (likely due to different content load timing).
Environment
- wry: 0.54.2
- tao: 0.34.5
- tauri: 2.10.2
- macOS: 15.4 (Sequoia)
- Architecture: aarch64 (Apple Silicon)
Suggested Fix
Override viewDidLayout (or layout) on WryWebViewParent in addition to drawRect:, so that traffic light repositioning happens during the layout phase -- not just the draw phase. This would catch all layout-triggered resets regardless of whether a redraw follows.
Alternatively, register an observer for NSViewFrameDidChangeNotification on the titlebar container view to detect when AppKit resets button positions.
Current Workaround
We replicate inset_traffic_lights in our own code and trigger it from:
- A frontend event emitted after React renders (catches initial layout reset)
- Tauri's
on_window_event for Resized/ThemeChanged/Focused (catches ongoing drift)
Description
trafficLightPosition/with_traffic_light_insetpositions are not maintained after AppKit layout passes triggered by content view replacement and webview content rendering. The traffic light buttons snap back to default macOS positions.Root Cause
WryWebViewParentrepositions traffic lights only in itsdrawRect:override (wry_web_view_parent.rs:42-47).drawRect:is a draw-phase method, not a layout-phase method. AppKit can reset button positions during layout passes that occur independently of (and sometimes after) the draw pass.Specifically:
setContentView:(atwkwebview/mod.rs:664) triggers a titlebar relayout that can reset button positions afterset_traffic_light_insetalready positioned them correctly at line 653.drawRect:call, the buttons stay at default positions.This is most visible in production builds where the bundled frontend loads synchronously from the app bundle, causing the content-triggered relayout to happen during initial display before any user interaction triggers a redraw.
Steps to Reproduce
titleBarStyle: "Overlay"andtrafficLightPosition: { "x": 16, "y": 22 }tauri build)The issue is intermittent and timing-dependent -- it reproduces more reliably in production builds than dev builds (likely due to different content load timing).
Environment
Suggested Fix
Override
viewDidLayout(orlayout) onWryWebViewParentin addition todrawRect:, so that traffic light repositioning happens during the layout phase -- not just the draw phase. This would catch all layout-triggered resets regardless of whether a redraw follows.Alternatively, register an observer for
NSViewFrameDidChangeNotificationon the titlebar container view to detect when AppKit resets button positions.Current Workaround
We replicate
inset_traffic_lightsin our own code and trigger it from:on_window_eventforResized/ThemeChanged/Focused(catches ongoing drift)