1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:48:11 +00:00

Ladybird: Implement the JavaScript console using a WebContentView

This aligns the Ladybird console implementation with the Browser console
a bit more, which uses OutOfProcessWebView for rendering console output.
This allows us to style the console output to try and match the system
theme.

Using a WebContentView is simpler than trying to style the old QTextEdit
widget, as the console output is HTML with built-in "-libweb-palette-*"
colors. These will override any color we set on the QTextEdit widget.
This commit is contained in:
Timothy Flynn 2023-04-22 21:57:08 -04:00 committed by Andreas Kling
parent 5af715e394
commit 4aca24481e
5 changed files with 80 additions and 22 deletions

View file

@ -11,25 +11,46 @@
#include "ConsoleWidget.h"
#include "Utilities.h"
#include "WebContentView.h"
#include <AK/StringBuilder.h>
#include <LibJS/MarkupGenerator.h>
#include <QLineEdit>
#include <QPalette>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>
namespace Ladybird {
static bool is_using_dark_system_theme(QWidget& widget)
{
// FIXME: Qt does not provide any method to query if the system is using a dark theme. We will have to implement
// platform-specific methods if we wish to have better detection. For now, this inspects if Qt is using a
// dark color for widget backgrounds using Rec. 709 luma coefficients.
// https://en.wikipedia.org/wiki/Rec._709#Luma_coefficients
auto color = widget.palette().color(widget.backgroundRole());
auto luma = 0.2126f * color.redF() + 0.7152f * color.greenF() + 0.0722f * color.blueF();
return luma <= 0.5f;
}
ConsoleWidget::ConsoleWidget()
{
setLayout(new QVBoxLayout);
m_output_view = new QTextEdit(this);
m_output_view->setReadOnly(true);
layout()->addWidget(m_output_view);
m_output_view = new WebContentView({}, WebView::EnableCallgrindProfiling::No);
if (is_using_dark_system_theme(*this))
m_output_view->update_palette(WebContentView::PaletteMode::Dark);
if (on_request_messages)
on_request_messages(0);
m_output_view->load("data:text/html,<html></html>"sv);
// Wait until our output WebView is loaded, and then request any messages that occurred before we existed
m_output_view->on_load_finish = [this](auto&) {
if (on_request_messages)
on_request_messages(0);
};
layout()->addWidget(m_output_view);
auto* bottom_container = new QWidget(this);
bottom_container->setLayout(new QHBoxLayout);
@ -139,12 +160,27 @@ void ConsoleWidget::print_source_line(StringView source)
void ConsoleWidget::print_html(StringView line)
{
m_output_view->append(QString::fromUtf8(line.characters_without_null_termination(), line.length()));
StringBuilder builder;
builder.append(R"~~~(
var p = document.createElement("p");
p.innerHTML = ")~~~"sv);
builder.append_escaped_for_json(line);
builder.append(R"~~~("
document.body.appendChild(p);
)~~~"sv);
// FIXME: Make it scroll to the bottom, using `window.scrollTo()` in the JS above.
// We used to call `m_output_view->scroll_to_bottom();` here, but that does not work because
// it runs synchronously, meaning it happens before the HTML is output via IPC above.
m_output_view->run_javascript(builder.string_view());
}
void ConsoleWidget::clear_output()
{
m_output_view->clear();
m_output_view->run_javascript(R"~~~(
document.body.innerHTML = "";
)~~~"sv);
}
void ConsoleWidget::reset()