cefsharp / cefsharp/CefSharp

WinForms - Viewport(?) does not take up size of control after container resize and leaves black space

Aperta
#5,174 14 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
C#
Stelle
10.3k
Fork
2.9k
Merge medio
5g 22h
PR unite (30g)
4

Descrizione

### Is there an existing issue for this?

- [x] I have searched both open/closed issues, no issue already exists.

### CefSharp Version

139.0.280

### Operating System

Windows 11

### Architecture

x64

### .Net Version

.NET Framework 4.7.2

### Implementation

WinForms

### Reproduction Steps

Form1.Designer.cs:
```cs
partial class Form1
{
///
/// Required designer variable.
///
private System.ComponentModel.IContainer components = null;

///
/// Clean up any resources being used.
///
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this._scrollPanel = new System.Windows.Forms.Panel();
this._browserContainer = new System.Windows.Forms.Panel();
this._browser = new CefSharp.WinForms.ChromiumWebBrowser();
this._buttonContainer = new System.Windows.Forms.Panel();
this._resizeButton = new System.Windows.Forms.Button();
this._loadButton = new System.Windows.Forms.Button();
this._scrollPanel.SuspendLayout();
this._browserContainer.SuspendLayout();
this._buttonContainer.SuspendLayout();
this.SuspendLayout();
//
// _scrollPanel
//
this._scrollPanel.AutoScroll = true;
this._scrollPanel.BackColor = System.Drawing.Color.DarkMagenta;
this._scrollPanel.Controls.Add(this._browserContainer);
this._scrollPanel.Controls.Add(this._buttonContainer);
this._scrollPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this._scrollPanel.Location = new System.Drawing.Point(0, 0);
this._scrollPanel.Name = "_scrollPanel";
this._scrollPanel.Size = new System.Drawing.Size(800, 450);
this._scrollPanel.TabIndex = 0;
//
// _browserContainer
//
this._browserContainer.BackColor = System.Drawing.Color.Plum;
this._browserContainer.Controls.Add(this._browser);
this._browserContainer.Dock = System.Windows.Forms.DockStyle.Top;
this._browserContainer.Location = new System.Drawing.Point(0, 80);
this._browserContainer.MinimumSize = new System.Drawing.Size(100, 100);
this._browserContainer.Name = "_browserContainer";
this._browserContainer.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0);
this._browserContainer.Size = new System.Drawing.Size(800, 100);
this._browserContainer.TabIndex = 1;
//
// _browser
//
this._browser.ActivateBrowserOnCreation = false;
this._browser.Dock = System.Windows.Forms.DockStyle.Fill;
this._browser.Location = new System.Drawing.Point(10, 0);
this._browser.MinimumSize = new System.Drawing.Size(100, 100);
this._browser.Name = "_browser";
this._browser.Size = new System.Drawing.Size(780, 100);
this._browser.TabIndex = 0;
//
// _buttonContainer
//
this._buttonContainer.BackColor = System.Drawing.Color.DarkSlateBlue;
this._buttonContainer.Controls.Add(this._resizeButton);
this._buttonContainer.Controls.Add(this._loadButton);
this._buttonContainer.Dock = System.Windows.Forms.DockStyle.Top;
this._buttonContainer.Location = new System.Drawing.Point(0, 0);
this._buttonContainer.Name = "_buttonContainer";
this._buttonContainer.Padding = new System.Windows.Forms.Padding(10);
this._buttonContainer.Size = new System.Drawing.Size(800, 80);
this._buttonContainer.TabIndex = 0;
//
// _resizeButton
//
this._resizeButton.Dock = System.Windows.Forms.DockStyle.Fill;
this._resizeButton.Location = new System.Drawing.Point(10, 40);
this._resizeButton.Name = "_resizeButton";
this._resizeButton.Size = new System.Drawing.Size(780, 30);
this._resizeButton.TabIndex = 0;
this._resizeButton.Text = "Resize";
this._resizeButton.UseVisualStyleBackColor = true;
this._resizeButton.Click += new System.EventHandler(this.ResizeButton_Click);
//
// _loadButton
//
this._loadButton.Dock = System.Windows.Forms.DockStyle.Top;
this._loadButton.Location = new System.Drawing.Point(10, 10);
this._loadButton.MinimumSize = new System.Drawing.Size(30, 30);
this._loadButton.Name = "_loadButton";
this._loadButton.Size = new System.Drawing.Size(780, 30);
this._loadButton.TabIndex = 1;
this._loadButton.Text = "Load Page";
this._loadButton.UseVisualStyleBackColor = true;
this._loadButton.Click += new System.EventHandler(this.LoadButton_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this._scrollPanel);
this.Name = "Form1";
this.Text = "Form1";
this._scrollPanel.ResumeLayout(false);
this._browserContainer.ResumeLayout(false);
this._buttonContainer.ResumeLayout(false);
this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.Panel _scrollPanel;
private System.Windows.Forms.Panel _buttonContainer;
private System.Windows.Forms.Button _resizeButton;
private System.Windows.Forms.Panel _browserContainer;
private CefSharp.WinForms.ChromiumWebBrowser _browser;
private System.Windows.Forms.Button _loadButton;
}
```

Form1.cs:
```cs
public partial class Form1 : Form
{

private static readonly string _html = @"


NewCefTest



1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20

";

public Form1()
{
InitializeComponent();

_browser.IsBrowserInitializedChanged += (s, e) =>
{
_browser.ShowDevTools();
};
}

private void ResizeButton_Click(object sender, EventArgs e)
{
if (!_browser.IsBrowserInitialized)
{
return;
}

IFrame mainFrame = _browser.GetMainFrame();
if (mainFrame == null)
{
_browserContainer.Height = _browser.MinimumSize.Height;
return;
}

// An example that gets the Document Height
var task = mainFrame.EvaluateScriptAsync("(function() { var body = document.body, html = document.documentElement; return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); })();");

//Continue execution on the UI Thread
task.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
var result = response.Success ? (response.Result ?? "null") : response.Message;

if (result is int height)
{
_browserContainer.Height = height;
}
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}

private void LoadButton_Click(object sender, EventArgs e)
{
_browser.LoadHtml(_html);
}
}
```

### Expected behavior

Based on the structure in `Form1.Designer.cs`, we first load the page with the `_loadButton`. Then, by clicking the `_resizeButton`, we should get the document height. We use that height to set the height of the `_browserContainer`, which causes the `_scrollPanel` to resize and add a scroll bar. This gives us the ability to scroll down to the bottom and view the 20th div in the document.
This allows us to eliminate the scroll inside the `_browser`, leaving us to be able to scroll only the panel.

### Actual behavior

Sadly, we don't get the expected behavior. Instead, we get a weird combination of "correct sizing of the control but no sizing of the viewport."
It seems like the _browser control gets resized since it's docked to fill in the _browserContainer, which we set.
However, the "Viewport" does not size after it. It's sort of "cut in half."

Image

Strangely, when I first resize using the button or resize the entire form horizontally, we receive a "size feedback" (I don't know the specific name for it) of the "viewport." This is definitely not the document itself, since the `_browser` control received the correct size from the script.

Image

The scroll for the document appears inside the `_browser` control, with which I can scroll all the way down and see the actual bottom of the document, which is the 20th div.

### Regression?

We are updating from version 98.x because we are experiencing DPI issues. After updating to the latest version (currently 139.0.280), we solved the DPI issue but encountered other problems. I've been switching between versions to see where this issue starts to appear.
I got to version 130.1.90, up to which the "black wall" did not appear. After that, I could not test from 131.3.50 to 137.0.100 for some reason. My debug started, but shortly after, before any form appeared, it stopped without any errors. For the life of me, I could not figure out why.
Starting with version 138.0.340, I could debug again and I experienced the "black wall."
In conclusion, based on my limited testing, the problem appears to start somewhere between versions 131.3.50 and 137.0.100.

### Known Workarounds

I've been looking through forums and GitHub issues, and I even dared to ask Copilot about the issue. I haven't seen anything related to this issue nor found a solution.

Copilot suggested adding the following to `app.manifest`:
```xml


PerMonitorV2
true/PM

```
I am not sure if its even relevant to the issue, but it did not help.

From what I've read here and there, as well as from Copilot, I should add arguments to CefSettings. I've ended up with the following, some of which we actually use in our current version 98.x implementation:
```cs
internal static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static int Main()
{
var settings = new CefSettings()
{
LogFile = "C:\\Debug.log", //You can customise this path
LogSeverity = LogSeverity.Info, // You can change the log level
};

settings.CefCommandLineArgs.Add("allow-access-from-files");
settings.CefCommandLineArgs.Add("allow-universal-access-from-files");
settings.CefCommandLineArgs.Add("disable-web-security");

settings.CefCommandLineArgs.Add("disable-gpu-vsync", "1");
settings.CefCommandLineArgs.Add("disable-gpu", "1");
settings.CefCommandLineArgs.Add("disable-gpu-compositing");

//Perform dependency check to make sure all relevant resources are in our output directory.
var initialized = Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

if (!initialized)
{
var exitCode = Cef.GetExitCode();

if (exitCode == ResultCode.NormalExitProcessNotified)
{
MessageBox.Show($"Cef.Initialize failed with {exitCode}, another process is already using cache path {string.Empty}");
}
else
{
MessageBox.Show($"Cef.Initialize failed with {exitCode}, check the log file for more details.");
}

return 0;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());

return 0;
}
}
```

Once again, sadly it did not change anything.

### Does this problem also occur in the CEF Sample Application

No, can't reproduce the issue, because of functional differences.

### Other information

Sadly I do not get any exception, since cef seems to be working correctly(?).
Inside `Debug.log` this is all I get:
```
[23116:21508:0919/114036.887:WARNING:chrome\browser\signin\account_consistency_mode_manager.cc:74] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured.
[23116:13632:0919/114040.790:ERROR:google_apis\gcm\engine\registration_request.cc:291] Registration response error message: DEPRECATED_ENDPOINT
[23116:13632:0919/114101.693:ERROR:google_apis\gcm\engine\connection_factory_impl.cc:434] Failed to connect to MCS endpoint with error -118
```

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Riproduci la sequenza di ridimensionamento da Form1.Designer.cs e Form1.cs: carica l'HTML, quindi esamina ResizeButton_Click e il relativo risultato dell'altezza del documento. Confronta i limiti di _browserContainer e _browser dopo il ridimensionamento; il lavoro è completato quando l'area del browser riflette l'altezza del documento caricato senza lasciare spazio nero.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
csharp
Ambito
desktop
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
55/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.