Skip to content

Commit 5cd2be6

Browse files
wayneforrestclaudeleaanthony
authored
fix(v3/windows): keep host-owned rasterization scale under visual hosting (#5761)
* fix(v3/windows): keep host-owned scale under visual hosting #5734 re-enabled WebView2 automatic monitor-scale detection (ShouldDetectMonitorScaleChanges) unconditionally to fix the mixed-DPI GPU-process crash. That is correct for the default windowed (HWND-child) hosting mode, but wrong under UseVisualHosting (COREWEBVIEW2_HOSTING_MODE_WINDOW_TO_VISUAL): the content is a DirectComposition visual decoupled from the child HWND that automatic detection tracks, so on a mixed-DPI monitor cross detection reads the wrong monitor and settles the visual on a stale rasterization scale -- the whole UI renders shrunk (small fonts) until something forces a re-layout. Gate the detection-enable on hosting mode: - windowed: enable detection (unchanged; keeps #5734's crash fix) - visual hosting: explicitly disable detection so the host owns the scale via resyncWebviewRasterizationScale (monitorScaleDetectionOn stays false). The module leaves detection at its platform default (enabled), so visual hosting must disable it explicitly -- merely skipping the enable would leave both Edge's detection and the host resync writing the scale (the two-writer race #5734 targets). Host-owned scale is reliable now that the by-value PutRasterizationScale bug (#5701) is fixed, and is the documented contract (WebView2Feedback #3665: detection-off is correct when the host puts the scale on every change). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(v3/windows): derive monitorScaleDetectionOn from actual controller state Query GetShouldDetectMonitorScaleChanges after the Put and set the single-writer flag from the controller's real state, not from the value requested. A failed PutShouldDetectMonitorScaleChanges could leave detection at its platform default (enabled) while monitorScaleDetectionOn stayed false, so resyncWebviewRasterizationScale would keep writing PutRasterizationScale concurrently with Edge — the two-writer scale(0,0) race this change removes. If the query itself fails, assume detection may be on and stand the host resync down. Addresses review feedback on #5761. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
1 parent 7d90315 commit 5cd2be6

1 file changed

Lines changed: 49 additions & 18 deletions

File tree

v3/pkg/application/webview_window_windows.go

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,28 +2383,59 @@ func (w *windowsWebviewWindow) setupChromium() {
23832383

23842384
chromium.Embed(w.hwnd)
23852385

2386-
// Ensure automatic monitor-scale detection is on. Published webview2
2387-
// module versions up to v1.0.27 disable ShouldDetectMonitorScaleChanges
2388-
// at controller creation (the in-repo module no longer does), leaving
2389-
// rasterization-scale updates entirely to the host's WM_DPICHANGED
2390-
// handling. In that
2391-
// host-managed mode, dragging the window across a mixed-DPI monitor
2392-
// boundary can make the embedded browser compute a degenerate
2393-
// scale(0,0) transform (ui/gfx/geometry/transform.cc NOTREACHED
2394-
// "is not invertible"); the resulting compositor frame is rejected by
2395-
// the viz process as a malformed Mojo message, which kills the GPU
2396-
// process, and after enough repeat kills the browser process gives up
2397-
// ("GPU process isn't usable. Goodbye.") taking the controller with
2398-
// it. Detection-on is the WebView2 default and keeps monitor-cross
2399-
// scale updates inside Edge, where that path is actually exercised;
2400-
// bounds stay raw-pixels. While detection is on, the host-side
2401-
// WM_DPICHANGED / un-minimise scale resyncs stand down (see
2386+
// Configure who owns the WebView2 rasterization scale on a monitor-DPI
2387+
// change. Two hosting modes need opposite answers:
2388+
//
2389+
// Windowed (HWND-child) hosting — the default: enable automatic
2390+
// monitor-scale detection. Published webview2 module versions up to
2391+
// v1.0.27 disabled ShouldDetectMonitorScaleChanges at controller creation
2392+
// (the in-repo module no longer does), leaving rasterization-scale updates
2393+
// entirely to the host's WM_DPICHANGED handling. In that host-managed mode,
2394+
// dragging the window across a mixed-DPI monitor boundary can make the
2395+
// embedded browser compute a degenerate scale(0,0) transform
2396+
// (ui/gfx/geometry/transform.cc NOTREACHED "is not invertible"); the
2397+
// resulting compositor frame is rejected by the viz process as a malformed
2398+
// Mojo message, which kills the GPU process, and after enough repeat kills
2399+
// the browser process gives up ("GPU process isn't usable. Goodbye.")
2400+
// taking the controller with it. Detection-on is the WebView2 default and
2401+
// keeps monitor-cross scale updates inside Edge, where that path is
2402+
// actually exercised; bounds stay raw-pixels. While detection is on, the
2403+
// host-side WM_DPICHANGED / un-minimise scale resyncs stand down (see
24022404
// monitorScaleDetectionOn) so the scale has exactly one writer.
2405+
//
2406+
// Visual hosting (UseVisualHosting -> COREWEBVIEW2_HOSTING_MODE_WINDOW_TO_VISUAL):
2407+
// the content is a DirectComposition visual, decoupled from the child HWND
2408+
// that automatic detection tracks. Across a mixed-DPI boundary detection
2409+
// then reads the wrong monitor and settles the visual on a stale scale, so
2410+
// the whole UI renders shrunk. There the host must own the scale via
2411+
// resyncWebviewRasterizationScale (correct per WebView2Feedback #3665, and
2412+
// reliable now that the by-value PutRasterizationScale bug is fixed). The
2413+
// module leaves detection at its platform default (enabled), so visual
2414+
// hosting must disable it *explicitly* — merely skipping the enable would
2415+
// leave detection on AND the host resync running, i.e. two writers racing,
2416+
// which is the scale(0,0) crash above. With detection off the host owns the
2417+
// scale via resyncWebviewRasterizationScale.
2418+
//
2419+
// Whichever mode: monitorScaleDetectionOn is set from the controller's
2420+
// *actual* ShouldDetectMonitorScaleChanges after the Put, never from the
2421+
// value we asked for. A failed Put can leave detection at its platform
2422+
// default (enabled) while we intended off; keying the flag off intent would
2423+
// then run the host resync against a detecting Edge — the exact two-writer
2424+
// race this guards against. The host stands down whenever detection is on so
2425+
// the rasterization scale keeps exactly one writer.
24032426
if controller := chromium.GetController(); controller != nil {
24042427
if c3 := controller.GetICoreWebView2Controller3(); c3 != nil {
2405-
if err := c3.PutShouldDetectMonitorScaleChanges(true); err != nil {
2406-
globalApplication.error("webview2: enable monitor scale detection: %v", err)
2428+
wantDetection := !globalApplication.options.Windows.UseVisualHosting
2429+
if err := c3.PutShouldDetectMonitorScaleChanges(wantDetection); err != nil {
2430+
globalApplication.error("webview2: set monitor scale detection to %v: %v", wantDetection, err)
2431+
}
2432+
if on, err := c3.GetShouldDetectMonitorScaleChanges(); err == nil {
2433+
w.monitorScaleDetectionOn = on
24072434
} else {
2435+
// Can't confirm the state: assume detection may be on and stand
2436+
// the host resync down. A cosmetic stale scale beats risking the
2437+
// two-writer GPU-process crash.
2438+
globalApplication.error("webview2: query monitor scale detection: %v", err)
24082439
w.monitorScaleDetectionOn = true
24092440
}
24102441
}

0 commit comments

Comments
 (0)