Skip to content

[Problem/Bug]: WebView2CompositionControl displays content blurred #5205

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
dreamsinbits opened this issue Apr 14, 2025 · 1 comment
Open
Assignees
Labels
bug Something isn't working

Comments

@dreamsinbits
Copy link

dreamsinbits commented Apr 14, 2025

What happened?

I'm using a WPF WebView2CompositionControl to display an instance of Monaco Editor, but the content is blurry. It looks like the content is rendered for a wrong DPI value.

At first I used the WebView2 control but this control has the issue that it is always shown on top of all other WPF controls. So I switched to the WebView2CompositionControl, the overlaying issue is fixed now, but the content is blurred. This was not the case when I used the WebView2 control.

Importance

Moderate. My app's user experience is affected, but still usable.

Runtime Channel

Stable release (WebView2 Runtime)

Runtime Version

No response

SDK Version

No response

Framework

WPF

Operating System

Windows 11

OS Version

No response

Repro steps

Steps to reproduce

Use this HTML for Monaco editor:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Editor</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <link rel="stylesheet"
          data-name="vs/editor/editor.main"
          href="./min/vs/editor/editor.main.css"/>
    <style>
        html, body {
            height: 100%;
            margin: 0;
        }

        #container {
            height: 100%;
        }
    </style>
</head>
<body>
<div id="container"></div>
<script src="./min/vs/loader.js"></script>
<script>
    require.config({paths: {'vs': './min/vs'}});
</script>
<script src="./min/vs/editor/editor.main.js"></script>
<script>
    // Hold a reference to the Monaco editor instance
    let monacoEditor;

    // Function to initialize the editor
    function initializeEditor(content, theme = 'vs-light') {
        require(['vs/editor/editor.main'], function () {
            if (monacoEditor) {
                return;
            }
            
            monacoEditor = monaco.editor.create(document.getElementById('container'), {
                value: content.toString(),
                automaticLayout: true,
                theme: theme,
            });
        });

        // Add a resize listener to resize Monaco Editor dynamically
        window.addEventListener('resize', () => {
            if (monacoEditor) {
                monacoEditor.layout();
            }
        });
    }
</script>
</body>
</html> 

Use this WPF XAML:

<UserControl
    x:Class="Example.TextEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:wpf="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
    d:DesignHeight="300"
    d:DesignWidth="300"
    mc:Ignorable="d">
    <Grid>
        <wpf:WebView2CompositionControl
            x:Name="TextEditorView"
            NavigationCompleted="TextEditorView_OnNavigationCompleted" />
    </Grid>
</UserControl>

Code behind:

using CommunityToolkit.Mvvm.Input;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace Example.TextEditor;

public partial class TextEditor : UserControl
{
       public TextEditor()
    {
        InitializeComponent();
        TextEditorView.Source = new Uri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Monaco\editor.html"));
    }

    private async Task InitializeEditorAsync()
    {
        if (_isEditorInitialized)
        {
            return;
        }
        
        var javaScriptString = ConvertToJavaScriptString(Text);
        var script = $"initializeEditor({javaScriptString})";

        await ExecuteJavaScriptAsync(script, TextEditorView);
        _isEditorInitialized = true;
    }
    
    private async Task<string> ExecuteJavaScriptAsync(string script, WebView2CompositionControl webview)
    {
        await webview.EnsureCoreWebView2Async();

        // Call the script in the WebView2 (this executes in the loaded HTML/JS context)
        var result = await webview.CoreWebView2.ExecuteScriptAsync(script);

        if (!string.IsNullOrEmpty(result))
        {
            result = ConvertToCSharpString(result);
        }

        return result;
    }

    private string ConvertToJavaScriptString(string text)
    {
        // JSON is compatible to JavaScript
        return JsonSerializer.Serialize(text);
    }

    private string ConvertToCSharpString(string javaScriptString)
    {
        // JSON is compatible to JavaScript
        return JsonSerializer.Deserialize<string>(javaScriptString);
    }

    private async void TextEditorView_OnNavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
    {
        try
        {
            await InitializeEditorAsync();
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
    }    
}

Expected Behavior

WebView2CompositionControl displays the HTML content exactly as the WebView2 control correctly rendered.

Actual Behavior

WebView2CompositionControl displays the HTML content blurred.

Repros in Edge Browser

No, issue does not reproduce in the corresponding Edge version

Regression

No, this never worked

Last working version (if regression)

No response

@dreamsinbits dreamsinbits added the bug Something isn't working label Apr 14, 2025
@dreamsinbits
Copy link
Author

I just found out that setting UseLayoutRounding="True" on the parent window fixes the problem. However, the other controls now look very sharp-edged. Unfortunately, setting it on the WebView2CompositionControl itself doesn't have any effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants