diff --git a/src/plugins/terminal/scrollback.cpp b/src/plugins/terminal/scrollback.cpp index 8a07c700f8d..f3bb6319734 100644 --- a/src/plugins/terminal/scrollback.cpp +++ b/src/plugins/terminal/scrollback.cpp @@ -20,7 +20,6 @@ Scrollback::Line::Line(int cols, const VTermScreenCell *cells, VTermState *vts) vterm_state_convert_color_to_rgb(vts, &m_cells[i].fg); vterm_state_convert_color_to_rgb(vts, &m_cells[i].bg); } - m_layout = std::make_unique(); } const VTermScreenCell *Scrollback::Line::cell(int i) const @@ -31,6 +30,9 @@ const VTermScreenCell *Scrollback::Line::cell(int i) const const QTextLayout &Scrollback::Line::layout(int version, const QFont &font, qreal lineSpacing) const { + if (!m_layout) + m_layout = std::make_unique(); + if (m_layoutVersion != version) { QString text; VTermColor defaultBg; diff --git a/src/plugins/terminal/scrollback.h b/src/plugins/terminal/scrollback.h index 63c18772b93..33799bdcd43 100644 --- a/src/plugins/terminal/scrollback.h +++ b/src/plugins/terminal/scrollback.h @@ -33,7 +33,7 @@ public: private: int m_cols; std::unique_ptr m_cells; - std::unique_ptr m_layout; + mutable std::unique_ptr m_layout; mutable int m_layoutVersion{-1}; }; diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 1cc965b0b8b..3d197ca31fd 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -29,6 +29,8 @@ #include #include +#include + Q_LOGGING_CATEGORY(terminalLog, "qtc.terminal", QtWarningMsg) using namespace Utils; @@ -36,6 +38,11 @@ using namespace Utils::Terminal; namespace Terminal { +using namespace std::chrono_literals; + +// Minimum time between two refreshes. +static const auto minRefreshInterval = 16ms; + TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) : QAbstractScrollArea(parent) , m_vterm(vterm_new(size().height(), size().width()), vterm_free) @@ -47,6 +54,7 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op , m_zoomInAction(Tr::tr("Zoom In")) , m_zoomOutAction(Tr::tr("Zoom Out")) , m_openParameters(openParameters) + , m_lastFlush(QDateTime::currentDateTime()) { setupVTerm(); setupFont(); @@ -66,13 +74,10 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - m_readDelayTimer.setSingleShot(true); - m_readDelayTimer.setInterval(10); + m_flushDelayTimer.setSingleShot(true); + m_flushDelayTimer.setInterval(minRefreshInterval); - connect(&m_readDelayTimer, &QTimer::timeout, this, [this] { - m_readDelayRestarts = 0; - onReadyRead(); - }); + connect(&m_flushDelayTimer, &QTimer::timeout, this, [this]() { flushVTerm(true); }); connect(&m_copyAction, &QAction::triggered, this, &TerminalWidget::copyToClipboard); connect(&m_pasteAction, &QAction::triggered, this, &TerminalWidget::pasteFromClipboard); @@ -109,14 +114,8 @@ void TerminalWidget::setupPty() m_process->setWorkingDirectory(*m_openParameters.workingDirectory); m_process->setEnvironment(env); - connect(m_process.get(), &QtcProcess::readyReadStandardOutput, this, [this] { - if (m_readDelayTimer.isActive()) - m_readDelayRestarts++; - - if (m_readDelayRestarts > 100) - return; - - m_readDelayTimer.start(); + connect(m_process.get(), &QtcProcess::readyReadStandardOutput, this, [this]() { + onReadyRead(false); }); connect(m_process.get(), &QtcProcess::done, this, [this] { @@ -138,7 +137,9 @@ void TerminalWidget::setupPty() } if (m_openParameters.m_exitBehavior == ExitBehavior::Restart) { - QMetaObject::invokeMethod(this, [this] { + QMetaObject::invokeMethod( + this, + [this] { m_process.reset(); setupPty(); }, @@ -411,17 +412,29 @@ void TerminalWidget::clearContents() // Fake a scrollback clearing QByteArray data{"\x1b[3J"}; vterm_input_write(m_vterm.get(), data.constData(), data.size()); - vterm_screen_flush_damage(m_vtermScreen); // Send Ctrl+L which will clear the screen writeToPty(QByteArray("\f")); } -void TerminalWidget::onReadyRead() +void TerminalWidget::onReadyRead(bool forceFlush) { QByteArray data = m_process->readAllRawStandardOutput(); vterm_input_write(m_vterm.get(), data.constData(), data.size()); - vterm_screen_flush_damage(m_vtermScreen); + + flushVTerm(forceFlush); +} + +void TerminalWidget::flushVTerm(bool force) +{ + if (force || QDateTime::currentDateTime() - m_lastFlush > minRefreshInterval) { + m_lastFlush = QDateTime::currentDateTime(); + vterm_screen_flush_damage(m_vtermScreen); + return; + } + + if (!m_flushDelayTimer.isActive()) + m_flushDelayTimer.start(); } const VTermScreenCell *TerminalWidget::fetchCell(int x, int y) const @@ -707,7 +720,7 @@ void TerminalWidget::applySizeChange() m_process->ptyData().resize(m_vtermSize); vterm_set_size(m_vterm.get(), m_vtermSize.height(), m_vtermSize.width()); - vterm_screen_flush_damage(m_vtermScreen); + flushVTerm(true); } void TerminalWidget::updateScrollBars() diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index 96e24f41172..ec0b0f80d85 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -76,7 +76,7 @@ protected: bool event(QEvent *event) override; protected: - void onReadyRead(); + void onReadyRead(bool forceFlush); void setupVTerm(); void setupFont(); void setupPty(); @@ -110,6 +110,8 @@ protected: void updateScrollBars(); + void flushVTerm(bool force); + private: std::unique_ptr m_process; @@ -151,14 +153,15 @@ private: QAction m_zoomInAction; QAction m_zoomOutAction; - QTimer m_readDelayTimer; - int m_readDelayRestarts{0}; + QTimer m_flushDelayTimer; int m_layoutVersion{0}; std::array m_currentColors; Utils::Terminal::OpenTerminalParameters m_openParameters; + + QDateTime m_lastFlush; }; } // namespace Terminal