From 37b9f9e363d92fd1e0455dde729c095d83167508 Mon Sep 17 00:00:00 2001 From: Matan Ziv-Av Date: Sat, 4 Jun 2022 19:52:41 +0300 Subject: [PATCH] Manage graphics placements vertical position on text reflow. When a line is reflowed then the vertical position of all graphics placements above or below it (as appropriate) are adjusted, so they remain in the same place relative to the text lines. --- src/Screen.cpp | 19 ++++++++++++++----- src/Screen.h | 2 +- src/history/HistoryScroll.h | 2 +- src/history/HistoryScrollFile.cpp | 2 +- src/history/HistoryScrollFile.h | 2 +- src/history/HistoryScrollNone.cpp | 2 +- src/history/HistoryScrollNone.h | 2 +- src/history/compact/CompactHistoryScroll.cpp | 10 +++++++++- src/history/compact/CompactHistoryScroll.h | 2 +- src/terminalDisplay/TerminalDisplay.cpp | 15 --------------- 10 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/Screen.cpp b/src/Screen.cpp index 4954508d..37eac80c 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -476,7 +476,6 @@ void Screen::resizeImage(int new_lines, int new_columns) if ((new_lines == _lines) && (new_columns == _columns)) { return; } - // Adjust scroll position, and fix glitches _oldTotalLines = getLines() + getHistLines(); _isResize = true; @@ -490,14 +489,20 @@ void Screen::resizeImage(int new_lines, int new_columns) while (!_screenLines.empty() && _history->isWrappedLine(_history->getLines() - 1)) { fastAddHistLine(); --cursorLine; + scrollPlacements(1); } - auto removedLines = _history->reflowLines(new_columns); + std::map deltas = {}; + auto removedLines = _history->reflowLines(new_columns, &deltas); // If _history size > max history size it will drop a line from _history. // We need to verify if we need to remove a URL. if (removedLines && _escapeSequenceUrlExtractor) { _escapeSequenceUrlExtractor->historyLinesRemoved(removedLines); } + + for (const auto &[pos, delta] : deltas) { + scrollPlacements(delta, INT64_MIN, pos); + } } if (_enableReflowLines && new_columns != _columns) { @@ -531,6 +536,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _screenLines.erase(_screenLines.begin() + currentPos + 1); _lineProperties.erase(_lineProperties.begin() + currentPos); --cursorLine; + scrollPlacements(1, currentPos); continue; } @@ -548,6 +554,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _screenLines.insert(_screenLines.begin() + currentPos + 1, std::move(values)); _lineProperties[currentPos] |= LINE_WRAPPED; ++cursorLine; + scrollPlacements(-1, currentPos); } currentPos += 1; } @@ -557,6 +564,7 @@ void Screen::resizeImage(int new_lines, int new_columns) while (cursorLine > new_lines - 1) { fastAddHistLine(); --cursorLine; + scrollPlacements(1); } if (_enableReflowLines) { @@ -572,6 +580,7 @@ void Screen::resizeImage(int new_lines, int new_columns) _lineProperties.insert(_lineProperties.begin(), lineProperty); _history->removeCells(); ++cursorLine; + scrollPlacements(-1); } } @@ -1121,7 +1130,7 @@ void Screen::scrollUp(int from, int n) moveImage(loc(0, from), loc(0, from + n), loc(_columns, _bottomMargin)); clearImage(loc(0, _bottomMargin - n + 1), loc(_columns - 1, _bottomMargin), ' '); if (_hasGraphics) { - scrollUpVisiblePlacements(n); + scrollPlacements(n); } } @@ -2043,14 +2052,14 @@ TerminalGraphicsPlacement_t *Screen::getGraphicsPlacement(unsigned int i) return _graphicsPlacements[i].get(); } -void Screen::scrollUpVisiblePlacements(int n) +void Screen::scrollPlacements(int n, qint64 below, qint64 above) { std::vector>::iterator i; int histMaxLines = _history->getMaxLines(); i = _graphicsPlacements.begin(); while (i != _graphicsPlacements.end()) { TerminalGraphicsPlacement_t *placement = i->get(); - if (placement->scrolling) { + if ((placement->scrolling && below == INT64_MAX) || (placement->row > below && placement->row < above)) { placement->row -= n; if (placement->row + placement->rows < -histMaxLines) { i = _graphicsPlacements.erase(i); diff --git a/src/Screen.h b/src/Screen.h index 91739e4a..31478c01 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -633,7 +633,6 @@ public: int X = 0, int Y = 0); TerminalGraphicsPlacement_t *getGraphicsPlacement(unsigned int i); - void scrollUpVisiblePlacements(int n); void delPlacements(int = 'a', qint64 = 0, qint64 = -1, int = 0, int = 0, int = 0); bool hasGraphics() const @@ -816,6 +815,7 @@ private: /* Graphics */ void addPlacement(std::unique_ptr &u); std::vector> _graphicsPlacements; + void scrollPlacements(int n, qint64 below = INT64_MAX, qint64 above = INT64_MAX); bool _hasGraphics; }; diff --git a/src/history/HistoryScroll.h b/src/history/HistoryScroll.h index 0f2901f2..c126dc2a 100644 --- a/src/history/HistoryScroll.h +++ b/src/history/HistoryScroll.h @@ -55,7 +55,7 @@ public: // modify history virtual void removeCells() = 0; - virtual int reflowLines(const int columns) = 0; + virtual int reflowLines(const int columns, std::map *deltas = nullptr) = 0; // // FIXME: Passing around constant references to HistoryType instances diff --git a/src/history/HistoryScrollFile.cpp b/src/history/HistoryScrollFile.cpp index 51061822..e8ff5508 100644 --- a/src/history/HistoryScrollFile.cpp +++ b/src/history/HistoryScrollFile.cpp @@ -104,7 +104,7 @@ void HistoryScrollFile::removeCells() _lineflags.removeLast(res * sizeof(unsigned char)); } -int HistoryScrollFile::reflowLines(const int columns) +int Konsole::HistoryScrollFile::reflowLines(const int columns, std::map *) { auto reflowFile = std::make_unique(); reflowData newLine; diff --git a/src/history/HistoryScrollFile.h b/src/history/HistoryScrollFile.h index bb430656..679e0cd1 100644 --- a/src/history/HistoryScrollFile.h +++ b/src/history/HistoryScrollFile.h @@ -38,7 +38,7 @@ public: // Modify history void removeCells() override; - int reflowLines(const int columns) override; + int reflowLines(const int columns, std::map * = nullptr) override; private: qint64 startOfLine(const int lineno) const; diff --git a/src/history/HistoryScrollNone.cpp b/src/history/HistoryScrollNone.cpp index 143ee702..21c52f02 100644 --- a/src/history/HistoryScrollNone.cpp +++ b/src/history/HistoryScrollNone.cpp @@ -70,7 +70,7 @@ void HistoryScrollNone::removeCells() { } -int HistoryScrollNone::reflowLines(int) +int Konsole::HistoryScrollNone::reflowLines(const int, std::map *) { return 0; } diff --git a/src/history/HistoryScrollNone.h b/src/history/HistoryScrollNone.h index 6720e082..6ecd2a5a 100644 --- a/src/history/HistoryScrollNone.h +++ b/src/history/HistoryScrollNone.h @@ -37,7 +37,7 @@ public: // Modify history (do nothing here) void removeCells() override; - int reflowLines(const int) override; + int reflowLines(const int, std::map * = nullptr) override; }; } diff --git a/src/history/compact/CompactHistoryScroll.cpp b/src/history/compact/CompactHistoryScroll.cpp index 2a571b54..21975fec 100644 --- a/src/history/compact/CompactHistoryScroll.cpp +++ b/src/history/compact/CompactHistoryScroll.cpp @@ -141,7 +141,7 @@ LineProperty CompactHistoryScroll::getLineProperty(const int lineNumber) const return _lineDatas.at(lineNumber).flag; } -int CompactHistoryScroll::reflowLines(const int columns) +int CompactHistoryScroll::reflowLines(const int columns, std::map *deltas) { std::vector newLineData; @@ -153,6 +153,8 @@ int CompactHistoryScroll::reflowLines(const int columns) }; int currentPos = 0; + int newPos = 0; + int delta = 0; while (currentPos < getLines()) { int startLine = startOfLine(currentPos); int endLine = startOfLine(currentPos + 1); @@ -168,9 +170,15 @@ int CompactHistoryScroll::reflowLines(const int columns) while (reflowLineLen(startLine, endLine) > columns && !(lineProperty & (LINE_DOUBLEHEIGHT_BOTTOM | LINE_DOUBLEHEIGHT_TOP))) { startLine += columns; setNewLine(newLineData, startLine + _indexBias, lineProperty | LINE_WRAPPED); + newPos++; } setNewLine(newLineData, endLine + _indexBias, lineProperty & ~LINE_WRAPPED); currentPos++; + newPos++; + if (deltas && delta != newPos - currentPos) { + (*deltas)[currentPos - getLines()] = newPos - currentPos - delta; + delta = newPos - currentPos; + } } _lineDatas = std::move(newLineData); diff --git a/src/history/compact/CompactHistoryScroll.h b/src/history/compact/CompactHistoryScroll.h index c333bd74..00a2323d 100644 --- a/src/history/compact/CompactHistoryScroll.h +++ b/src/history/compact/CompactHistoryScroll.h @@ -37,7 +37,7 @@ public: void setMaxNbLines(const int lineCount); - int reflowLines(const int columns) override; + int reflowLines(const int columns, std::map *deltas = nullptr) override; private: /** diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp index 1edc5338..7feebc76 100644 --- a/src/terminalDisplay/TerminalDisplay.cpp +++ b/src/terminalDisplay/TerminalDisplay.cpp @@ -1002,21 +1002,6 @@ void TerminalDisplay::updateImageSize() if (_resizing) { showResizeNotification(); - if (oldLines != _lines) { - // An image's vertical position is relative to top line of the - // terminal, but text is relative to the bottom line, so the - // position needs adjusting when the terminal is resized. - int histLines = 0; - int change = oldLines - _lines; - if (_screenWindow && _screenWindow->screen()) { - histLines = _screenWindow->screen()->getHistLines(); - } - if (histLines) { - _screenWindow->screen()->scrollUpVisiblePlacements(qMax(-histLines, change)); - } else if (oldLines > _lines && cursorPosition().y() >= oldLines - change) { - _screenWindow->screen()->scrollUpVisiblePlacements(cursorPosition().y() - _lines + 1); - } - } Q_EMIT changedContentSizeSignal(_contentRect.height(), _contentRect.width()); // expose resizeEvent }