Terminal: Move color mapping to widget

This allows us to easily update the view when the colors are changed
in the settings.

Change-Id: I0b4f150b4fc9cec9aee2796d63f2395e05ce70df
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-03-22 15:39:55 +01:00
parent d5b419dfa8
commit 5341570572
6 changed files with 75 additions and 100 deletions

View File

@@ -10,15 +10,11 @@
namespace Terminal::Internal {
Scrollback::Line::Line(int cols, const VTermScreenCell *cells, VTermState *vts)
Scrollback::Line::Line(int cols, const VTermScreenCell *cells)
: m_cols(cols)
, m_cells(std::make_unique<VTermScreenCell[]>(cols))
{
memcpy(m_cells.get(), cells, cols * sizeof(cells[0]));
for (int i = 0; i < cols; ++i) {
vterm_state_convert_color_to_rgb(vts, &m_cells[i].fg);
vterm_state_convert_color_to_rgb(vts, &m_cells[i].bg);
}
}
const VTermScreenCell *Scrollback::Line::cell(int i) const
@@ -31,9 +27,9 @@ Scrollback::Scrollback(size_t capacity)
: m_capacity(capacity)
{}
void Scrollback::emplace(int cols, const VTermScreenCell *cells, VTermState *vts)
void Scrollback::emplace(int cols, const VTermScreenCell *cells)
{
m_deque.emplace_front(cols, cells, vts);
m_deque.emplace_front(cols, cells);
while (m_deque.size() > m_capacity) {
m_deque.pop_back();
}

View File

@@ -21,7 +21,7 @@ public:
class Line
{
public:
Line(int cols, const VTermScreenCell *cells, VTermState *vts);
Line(int cols, const VTermScreenCell *cells);
Line(Line &&other) = default;
Line() = delete;
@@ -44,9 +44,7 @@ public:
const Line &line(size_t index) const { return m_deque.at(index); };
const std::deque<Line> &lines() const { return m_deque; };
void emplace(int cols,
const VTermScreenCell *cells,
VTermState *vts);
void emplace(int cols, const VTermScreenCell *cells);
void popto(int cols, VTermScreenCell *cells);
void clear();

View File

@@ -89,6 +89,18 @@ struct TerminalSurfacePrivate
vterm_state_set_unrecognised_fallbacks(vts, &m_vtermStateFallbacks, this);
vterm_state_set_bold_highbright(vts, true);
VTermColor fg;
VTermColor bg;
vterm_color_indexed(&fg, ColorIndex::Foreground);
vterm_color_indexed(&bg, ColorIndex::Background);
vterm_state_set_default_colors(vts, &fg, &bg);
for (int i = 0; i < 16; ++i) {
VTermColor col;
vterm_color_indexed(&col, i);
vterm_state_set_palette_color(vts, i, &col);
}
vterm_screen_reset(m_vtermScreen, 1);
}
@@ -101,6 +113,25 @@ struct TerminalSurfacePrivate
return QSize(cols, rows);
}
std::variant<int, QColor> toVariantColor(const VTermColor &color)
{
if (color.type & VTERM_COLOR_DEFAULT_BG)
return ColorIndex::Background;
else if (color.type & VTERM_COLOR_DEFAULT_FG)
return ColorIndex::Foreground;
else if (color.type & VTERM_COLOR_INDEXED) {
if (color.indexed.idx >= 16) {
VTermColor c = color;
vterm_state_convert_color_to_rgb(vterm_obtain_state(m_vterm.get()), &c);
return toQColor(c);
}
return color.indexed.idx;
} else if (color.type == VTERM_COLOR_RGB)
return toQColor(color);
else
return -1;
}
TerminalCell toCell(const VTermScreenCell &cell)
{
TerminalCell result;
@@ -113,13 +144,8 @@ struct TerminalSurfacePrivate
if (static_cast<bool>(cell.attrs.reverse))
std::swap(fg, bg);
const QColor cellBgColor = toQColor(*bg);
const QColor cellFgColor = toQColor(*fg);
if (cellBgColor != m_defaultBgColor)
result.background = toQColor(*bg);
result.foreground = cellFgColor;
result.backgroundColor = toVariantColor(*bg);
result.foregroundColor = toVariantColor(*fg);
result.bold = cell.attrs.bold;
result.strikeOut = cell.attrs.strike;
@@ -151,26 +177,6 @@ struct TerminalSurfacePrivate
return result;
}
VTermColor defaultBgColor() const
{
VTermColor defaultBg;
if (!m_altscreen) {
VTermColor defaultFg;
vterm_state_get_default_colors(vterm_obtain_state(m_vterm.get()),
&defaultFg,
&defaultBg);
// We want to compare the cell bg against this later and cells don't
// set DEFAULT_BG
defaultBg.type = VTERM_COLOR_RGB;
return defaultBg;
} // This is a slightly better guess when in an altscreen
VTermPos vtp{0, 0};
static VTermScreenCell refCell{};
vterm_screen_get_cell(m_vtermScreen, vtp, &refCell);
return refCell.bg;
}
// Callbacks from vterm
void invalidate(VTermRect rect)
{
@@ -185,7 +191,7 @@ struct TerminalSurfacePrivate
int sb_pushline(int cols, const VTermScreenCell *cells)
{
m_scrollback->emplace(cols, cells, vterm_obtain_state(m_vterm.get()));
m_scrollback->emplace(cols, cells);
emit q->fullSizeChanged(q->fullSize());
return 1;
}
@@ -284,8 +290,6 @@ struct TerminalSurfacePrivate
static VTermScreenCell refCell{};
VTermPos vtp{y, x};
vterm_screen_get_cell(m_vtermScreen, vtp, &refCell);
vterm_screen_convert_color_to_rgb(m_vtermScreen, &refCell.fg);
vterm_screen_convert_color_to_rgb(m_vtermScreen, &refCell.bg);
return &refCell;
}
@@ -295,7 +299,6 @@ struct TerminalSurfacePrivate
VTermScreenCallbacks m_vtermScreenCallbacks;
VTermStateFallbacks m_vtermStateFallbacks;
QColor m_defaultBgColor;
Cursor m_cursor;
QString m_currentCommand;
@@ -352,8 +355,14 @@ std::u32string::value_type TerminalSurface::fetchCharAt(int x, int y) const
TerminalCell TerminalSurface::fetchCell(int x, int y) const
{
static TerminalCell
emptyCell{1, {}, {}, false, {}, std::nullopt, QTextCharFormat::NoUnderline, false};
static TerminalCell emptyCell{1,
{},
{},
false,
ColorIndex::Foreground,
ColorIndex::Background,
QTextCharFormat::NoUnderline,
false};
QTC_ASSERT(y >= 0, return emptyCell);
QTC_ASSERT(y < fullSize().height() && x < fullSize().width(), return emptyCell);
@@ -400,33 +409,6 @@ void TerminalSurface::flush()
vterm_screen_flush_damage(d->m_vtermScreen);
}
void TerminalSurface::setColors(QColor foreground, QColor background)
{
VTermState *vts = vterm_obtain_state(d->m_vterm.get());
VTermColor fg;
VTermColor bg;
vterm_color_rgb(&fg, foreground.red(), foreground.green(), foreground.blue());
vterm_color_rgb(&bg, background.red(), background.green(), background.blue());
d->m_defaultBgColor = background;
vterm_state_set_default_colors(vts, &fg, &bg);
vterm_screen_reset(d->m_vtermScreen, 1);
}
void TerminalSurface::setAnsiColor(int index, QColor color)
{
VTermState *vts = vterm_obtain_state(d->m_vterm.get());
VTermColor col;
vterm_color_rgb(&col, color.red(), color.green(), color.blue());
vterm_state_set_palette_color(vts, index, &col);
vterm_screen_reset(d->m_vtermScreen, 1);
}
void TerminalSurface::pasteFromClipboard(const QString &clipboardText)
{
if (clipboardText.isEmpty())
@@ -496,11 +478,6 @@ Cursor TerminalSurface::cursor() const
return cursor;
}
QColor TerminalSurface::defaultBgColor() const
{
return toQColor(d->defaultBgColor());
}
ShellIntegration *TerminalSurface::shellIntegration() const
{
return d->m_shellIntegration;

View File

@@ -18,14 +18,16 @@ class Scrollback;
struct TerminalSurfacePrivate;
enum ColorIndex { Foreground = 16, Background = 17 };
struct TerminalCell
{
int width;
QString text;
bool bold{false};
bool italic{false};
QColor foreground;
std::optional<QColor> background;
std::variant<int, QColor> foregroundColor;
std::variant<int, QColor> backgroundColor;
QTextCharFormat::UnderlineStyle underlineStyle{QTextCharFormat::NoUnderline};
bool strikeOut{false};
};
@@ -81,9 +83,6 @@ public:
void dataFromPty(const QByteArray &data);
void flush();
void setColors(QColor foreground, QColor background);
void setAnsiColor(int index, QColor color);
void pasteFromClipboard(const QString &text);
void sendKey(Qt::Key key);
@@ -94,8 +93,6 @@ public:
Cursor cursor() const;
QColor defaultBgColor() const;
ShellIntegration *shellIntegration() const;
signals:

View File

@@ -218,14 +218,8 @@ void TerminalWidget::setupColors()
m_currentColors = newColors;
m_surface->setColors(TerminalSettings::instance().foregroundColor.value(),
TerminalSettings::instance().backgroundColor.value());
for (int i = 0; i < 16; ++i) {
m_surface->setAnsiColor(i, TerminalSettings::instance().colors[i].value());
}
clearContents();
updateViewport();
update();
}
void TerminalWidget::setupActions()
@@ -336,6 +330,18 @@ void TerminalWidget::configBlinkTimer()
}
}
QColor TerminalWidget::toQColor(std::variant<int, QColor> color) const
{
if (std::holds_alternative<int>(color)) {
int idx = std::get<int>(color);
if (idx >= 0 && idx < 18)
return m_currentColors[idx];
return m_currentColors[Internal::ColorIndex::Background];
}
return std::get<QColor>(color);
}
void TerminalWidget::setFont(const QFont &font)
{
m_font = font;
@@ -747,8 +753,9 @@ void TerminalWidget::paintSelectionOrBackground(QPainter &p,
if (isInSelection)
p.fillRect(cellRect, TerminalSettings::instance().selectionColor.value());
else if (cell.background)
p.fillRect(cellRect, *cell.background);
else if (!(std::holds_alternative<int>(cell.backgroundColor)
&& std::get<int>(cell.backgroundColor) == 17))
p.fillRect(cellRect, toQColor(cell.backgroundColor));
}
int TerminalWidget::paintCell(QPainter &p,
@@ -759,7 +766,7 @@ int TerminalWidget::paintCell(QPainter &p,
{
paintSelectionOrBackground(p, cell, cellRect, gridPos);
p.setPen(cell.foreground);
p.setPen(toQColor(cell.foregroundColor));
f.setBold(cell.bold);
f.setItalic(cell.italic);
@@ -909,12 +916,10 @@ void TerminalWidget::paintEvent(QPaintEvent *event)
p.save();
const QColor defaultBgColor = m_surface->defaultBgColor();
if (paintLog().isDebugEnabled())
p.fillRect(event->rect(), QColor::fromRgb(rand() % 60, rand() % 60, rand() % 60));
else
p.fillRect(event->rect(), defaultBgColor);
p.fillRect(event->rect(), m_currentColors[Internal::ColorIndex::Background]);
int scrollOffset = verticalScrollBar()->value();
int offset = -(scrollOffset * m_cellSize.height());
@@ -929,7 +934,8 @@ void TerminalWidget::paintEvent(QPaintEvent *event)
p.restore();
p.fillRect(QRectF{{0, 0}, QSizeF{(qreal) width(), topMargin()}}, defaultBgColor);
p.fillRect(QRectF{{0, 0}, QSizeF{(qreal) width(), topMargin()}},
m_currentColors[Internal::ColorIndex::Background]);
if (selectionLog().isDebugEnabled()) {
if (m_selection)
@@ -1295,8 +1301,7 @@ bool TerminalWidget::event(QEvent *event)
if (event->type() == QEvent::Paint) {
QPainter p(this);
p.fillRect(QRect(QPoint(0, 0), size()),
TerminalSettings::instance().backgroundColor.value());
p.fillRect(QRect(QPoint(0, 0), size()), m_currentColors[Internal::ColorIndex::Background]);
return true;
}

View File

@@ -166,6 +166,8 @@ protected:
void configBlinkTimer();
QColor toQColor(std::variant<int, QColor> color) const;
private:
std::unique_ptr<Utils::QtcProcess> m_process;
std::unique_ptr<Internal::TerminalSurface> m_surface;