Skip to content

[Problem/Bug]: WebView2 Window Extends Beyond Content Bounds in Multi-Monitor DPI Scaling Scenarios #5253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
samfilip opened this issue May 23, 2025 · 0 comments
Assignees
Labels
bug Something isn't working regression Something used to work but doesn't anymore

Comments

@samfilip
Copy link

samfilip commented May 23, 2025

What happened?

WebView2 Window Extends Beyond Content Bounds in Multi-Monitor DPI Scaling Scenarios

Environment

  • WebView2 SDK: 1.0.1823.32
  • .NET Framework: 4.8
  • Application: WebView2 Core in VSTO Add-in for PowerPoint
  • OS: Windows 10/11 (multiple versions)
  • Hardware: Multi-monitor setup with different DPI scaling factors, for exampe: (primary: 150% at 1920x1200, secondary: 175% at 4K)

Issue Description

When hosting WebView2 in a multi-monitor environment with different DPI scaling factors, the WebView2 host window (Chrome_WidgetWin_0) extends beyond its content bounds. This extended section is actually displaying the content that is behind the PowerPoint slideshow presentation window which creates a very unusual user experience. This issue appears to be specific to WebView2's window management and persists regardless of DPI awareness context. We are not explicitly setting BoundsMode, but it defaults to UseRawPixels and we have tried to fix it using UseRasterizationScale without any luck. We generally get perfect placement and sizing when system dpi matches the external monitor dpi.

This was working on our initial release in 2023, when runtime version 118 was the latest stable. We noticed this regression in early 2024, and our best guess is around runtime 120 based on time and similar issues. We have been unable to test and install against these runtimes to see exactly where the regression took place.

Detailed Observations

  1. WebView2 Content Window:
    • Correctly positioned and sized according to the bounds passed to SetBoundsAndZoomFactor
    • Reports correct innerWidth (3192) and innerHeight (1756) in browser dev tools window
    • When using inspect/UIAViewer, the actual size is (systemDPI - 144 or 150% Scale, external monitor DPI 168 or 175% Scale):
      • Chrome_WidgetWin_1: Location:{x: -860 y: -2113 w:2736, h: 1505}
      • Chrome_WidgetWin_0: Location:{x: -860 y: -2113 w:3192, h: 1756}
  2. Behavior with different WebView2 bounds modes:
    • UseRawPixels: Content is too small, but Chrome_WidgetWin_0 is positioned correctly.
    • UseRasterizationScale: Content (Chrome_WidgetWin_1) is correctly sized and positioned, but parent (Chrome_WidgetWin_0)
      window still extends beyond bounds.
    • Setting RasterizationScale = 1 or some other value may change the size of the content but not the bounds
  3. PowerPoint Window:
    • We initialize our WebView2 Controllers with the pptHWND and then reparent them to the slideshowHWND when the
      presentation begins.
    • We have tried reworking this, at the cost of performance, to only initialize the WV2 controllers with the slideshowHWND but the same behavior persists.
    • We have also tried ensuring the .Navigate is called with the URL only after setting the Bounds, as well as manipulating the sizing with Zoom and RasterizationScale but to no avail.

Set Bounds: {Left: 49.41426, Top: 47.61421, Width: 3192.6, Height: 1756.2}
Dev tools reported dimensions:
window.innerWidth = 1825
window.innerHeight = 1004

Image

Image

Expected Behavior

The WebView2 host window (Chrome_WidgetWin_0) and content window (Chrome_WidgetWin_1) should follow the bounds set via SetBoundsAndZoomFactor or Bounds = assignment.

Code Sample

// Create and initialize WebView2 for WV2EmbedManager
private async void InitializeWebView2()
{
  CoreWebView2EnvironmentOptions options = new CoreWebView2EnvironmentOptions();

// pass null to use latest installed runtime
  webView2Environment = await CoreWebView2Environment.CreateAsync(null, dataPath, options).ConfigureAwait(true);

// We manage cookies and authentication with an independent controller
  independentController = await webView2Environment.CreateCoreWebView2ControllerAsync(pptHWND).ConfigureAwait(true);

  controllersByURL = new Dictionary<string, CoreWebView2Controller>();
  controllerQueue = new Queue<CoreWebView2Controller>();

  for (int i = 0; i < CONTROLLER_COUNT; i++)
  {
   CoreWebView2Controller controller = await webView2Environment.CreateCoreWebView2ControllerAsync(pptHWND).ConfigureAwait(true);

   controller.CoreWebView2.Settings.UserAgent = Util.GenerateWebView2UserAgent();
   controller.CoreWebView2.Settings.AreDevToolsEnabled = Util.DevToolsEnabled();
	 controller.CoreWebView2.Settings.IsZoomControlEnabled = true;
	 controller.CoreWebView2.Settings.AreDefaultContextMenusEnabled = true;
   
   await controller.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(listeners).ConfigureAwait(true);
   controller.CoreWebView2.WebMessageReceived += HandleWebMessageReceivedEvent;

   controller.CoreWebView2.NavigationCompleted += NavDone;
   // We have also tried setting this to false
   controller.ShouldDetectMonitorScaleChanges = true;
   // We've tried to explicity set up with both BoundsMode options with different Rectangle dimensions, with different but negative results
   // controller.BoundsMode = CoreWebView2BoundsMode.UseRawPixels;
   // controller.BoundsMode = CoreWebView2BoundsMode.UseRasterizationScale;
   // controller.RasterizationScaleChanged += HandleRasterizationScaleChanged;
   
   // we create a controller for each slide and cache 3 at a time
   // the NavDone event may fire before setting the bounds but this doesn't seem    // to be the issue as cold starting a presentation from the slide with a
   // a browser doesn't display this issue and refreshing the page doesn't have a
   // an effect on the bounds.
   controllerQueue.Enqueue(controller);
  }
}

// Get bounds from PowerPoint placeholder {Left: 49.41426, Top: 47.61421, Width: 3192.6, Height: 1756.2}
RECT placeholderRect = shapeInPixels.CoordsInPixels(
    placeholderShape.Top,
    placeholderShape.Left,
    placeholderShape.Width,
    placeholderShape.Height
);

private void NavDone(object sender, CoreWebView2NavigationCompletedEventArgs args)
{
    if (!(sender is CoreWebView2)) return;

    if (((CoreWebView2)sender) == currentVizEmbed?.CoreWebView2)
    {
		    // the core logic is that it sets IsVisible to true
        ShowPoll();
    }
}

public void BeginSlideShow(int slideshowHWND, List<PESlide> slides, Func<bool> checkEOS)
{
    this.slideshowHWND = slideshowHWND;
    IntPtr slideshowHandle = new IntPtr(slideshowHWND);

    foreach (CoreWebView2Controller controller in controllerQueue)
    {
        // reset ParentWindow from from ppt HWND to SlideshowHWND
        controller.ParentWindow = slideshowHandle;
    }
    UpdateAllSlides(slides);
    this.checkEOS = checkEOS;
}

// Set bounds and zoom factor in ShowSlide(int index) method
controller.SetBoundsAndZoomFactor(
    new Rectangle(
        placeholderRect.X,
        placeholderRect.Y,
        placeholderRect.Width,
        placeholderRect.Height
    ),
    1.0 // Always set to 1.0, this doesn't seem to be the issue
);

Importance

Important. My app's user experience is significantly compromised.

Runtime Channel

Stable release (WebView2 Runtime)

Runtime Version

136.0.3240.76

SDK Version

1.0.1823.32

Framework

Other

Operating System

Windows 11

OS Version

10.0.26100

Repro steps

Reproduction Steps

  1. Create a PowerPoint presentation with a placeholder shape
  2. Use WebView2 to create a browser overlay on this placeholder
  3. Set browser bounds using SetBoundsAndZoomFactor to match placeholder dimensions
  4. Present the PowerPoint slideshow on a secondary monitor with different DPI scaling than primary
  5. Observe that while content is positioned correctly, the host window extends beyond bounds if DPI scaling of secondary monitor is higher than the primary/system DPI or the web content is bigger than the bounds if lower than the system DPI.

Repros in Edge Browser

No, issue does not reproduce in the corresponding Edge version

Regression

Regression in newer Runtime

Last working version (if regression)

1.0.1823.32, Runtime: 118.0.xxxx

@samfilip samfilip added the bug Something isn't working label May 23, 2025
@github-actions github-actions bot added the regression Something used to work but doesn't anymore label May 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working regression Something used to work but doesn't anymore
Projects
None yet
Development

No branches or pull requests

2 participants