diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp index 2cef7018..2f3e498a 100644 --- a/src/terminalDisplay/TerminalDisplay.cpp +++ b/src/terminalDisplay/TerminalDisplay.cpp @@ -471,8 +471,6 @@ TerminalDisplay::TerminalDisplay(QWidget* parent) , _filterChain(new TerminalImageFilterChain(this)) , _filterUpdateRequired(true) , _cursorShape(Enum::BlockCursor) - , _cursorColor(QColor()) - , _cursorTextColor(QColor()) , _antialiasText(true) , _useFontLineCharacters(false) , _sessionController(nullptr) @@ -565,13 +563,21 @@ TerminalDisplay::TerminalDisplay(QWidget* parent) connect(KonsoleSettings::self(), &KonsoleSettings::configChanged, this, &TerminalDisplay::setupHeaderVisibility); _terminalPainter = new TerminalPainter(this); + connect(this, &TerminalDisplay::drawContents, _terminalPainter, &TerminalPainter::drawContents); + connect(this, &TerminalDisplay::drawCurrentResultRect, _terminalPainter, &TerminalPainter::drawCurrentResultRect); + connect(this, &TerminalDisplay::highlightScrolledLines, _terminalPainter, &TerminalPainter::highlightScrolledLines); + connect(this, &TerminalDisplay::highlightScrolledLinesRegion, _terminalPainter, &TerminalPainter::highlightScrolledLinesRegion); + connect(this, &TerminalDisplay::drawBackground, _terminalPainter, &TerminalPainter::drawBackground); + connect(this, &TerminalDisplay::drawCursor, _terminalPainter, &TerminalPainter::drawCursor); + connect(this, &TerminalDisplay::drawCharacters, _terminalPainter, &TerminalPainter::drawCharacters); + connect(this, &TerminalDisplay::drawInputMethodPreeditString, _terminalPainter, &TerminalPainter::drawInputMethodPreeditString); auto ldrawBackground = [this](QPainter &painter, const QRect &rect, const QColor &backgroundColor, bool useOpacitySetting) { - _terminalPainter->drawBackground(painter, rect, backgroundColor, useOpacitySetting); + emit drawBackground(painter, rect, backgroundColor, useOpacitySetting); }; auto ldrawContents = [this](QPainter &paint, const QRect &rect, bool friendly) { - _terminalPainter->drawContents(paint, rect, friendly); + emit drawContents(_image, paint, rect, friendly, _imageSize, _bidiEnabled, _fixedFont, _lineProperties); }; auto lgetBackgroundColor = [this]() { return getBackgroundColor(); @@ -671,16 +677,6 @@ void TerminalDisplay::resetCursorStyle() } } -void TerminalDisplay::setKeyboardCursorColor(const QColor& color) -{ - _cursorColor = color; -} - -void TerminalDisplay::setKeyboardCursorTextColor(const QColor& color) -{ - _cursorTextColor = color; -} - void TerminalDisplay::setOpacity(qreal opacity) { QColor color(_blendColor); @@ -924,7 +920,12 @@ void TerminalDisplay::updateImage() } if (_highlightScrolledLinesControl.enabled) { - dirtyRegion |= _terminalPainter->highlightScrolledLinesRegion(dirtyRegion.isEmpty()); + dirtyRegion |= emit highlightScrolledLinesRegion(dirtyRegion.isEmpty(), + _highlightScrolledLinesControl.timer, + _highlightScrolledLinesControl.previousScrollCount, + _highlightScrolledLinesControl.rect, + _highlightScrolledLinesControl.needToClear, + HIGHLIGHT_SCROLLED_LINES_WIDTH); } _screenWindow->resetScrollCount(); @@ -983,7 +984,7 @@ void TerminalDisplay::paintEvent(QPaintEvent* pe) for (const QRect &rect : region) { dirtyImageRegion += widgetToImage(rect); - _terminalPainter->drawBackground(paint, rect, getBackgroundColor(), true /* use opacity setting */); + emit drawBackground(paint, rect, getBackgroundColor(), true /* use opacity setting */); } if (_displayVerticalLine) { @@ -999,11 +1000,13 @@ void TerminalDisplay::paintEvent(QPaintEvent* pe) paint.setRenderHint(QPainter::TextAntialiasing, _antialiasText); for (const QRect &rect : qAsConst(dirtyImageRegion)) { - _terminalPainter->drawContents(paint, rect, false); + emit drawContents(_image, paint, rect, false, _imageSize, _bidiEnabled, _fixedFont, _lineProperties); + } + emit drawCurrentResultRect(paint, _searchResultRect); + if (_highlightScrolledLinesControl.enabled) { + emit highlightScrolledLines(paint, _highlightScrolledLinesControl.timer, _highlightScrolledLinesControl.rect); } - _terminalPainter->drawCurrentResultRect(paint); - _terminalPainter->highlightScrolledLines(paint); - _terminalPainter->drawInputMethodPreeditString(paint, preeditRect()); + emit drawInputMethodPreeditString(paint, preeditRect(), _inputMethodData, _image); paintFilters(paint); const bool drawDimmed = _dimWhenInactive && !hasFocus(); @@ -3131,12 +3134,6 @@ void TerminalDisplay::applyProfile(const Profile::Ptr &profile) // cursor shape setKeyboardCursorShape(Enum::CursorShapeEnum(profile->property(Profile::CursorShape))); - // cursor color - // an invalid QColor is used to inform the view widget to - // draw the cursor using the default color( matching the text) - setKeyboardCursorColor(profile->useCustomCursorColor() ? profile->customCursorColor() : QColor()); - setKeyboardCursorTextColor(profile->useCustomCursorColor() ? profile->customCursorTextColor() : QColor()); - // word characters setWordCharacters(profile->wordCharacters()); @@ -3155,6 +3152,8 @@ void TerminalDisplay::applyProfile(const Profile::Ptr &profile) _filterChain->setReverseUrlHints(profile->property(Profile::ReverseUrlHints)); _peekPrimaryShortcut = profile->peekPrimaryKeySequence(); + + _terminalPainter->applyProfile(profile); } void TerminalDisplay::printScreen() diff --git a/src/terminalDisplay/TerminalDisplay.h b/src/terminalDisplay/TerminalDisplay.h index 4e4facc4..4cdcdc8b 100644 --- a/src/terminalDisplay/TerminalDisplay.h +++ b/src/terminalDisplay/TerminalDisplay.h @@ -166,36 +166,6 @@ public: */ void resetCursorStyle(); - /** - * Sets the color used to draw the keyboard cursor. - * - * The keyboard cursor defaults to using the foreground color of the character - * underneath it. - * - * @param color By default, the widget uses the color of the - * character under the cursor to draw the cursor, and inverts the - * color of that character to make sure it is still readable. If @p - * color is a valid QColor, the widget uses that color to draw the - * cursor. If @p color is not an valid QColor, the widget falls back - * to the default behavior. - */ - void setKeyboardCursorColor(const QColor &color); - - /** - * Sets the color used to draw the character underneath the keyboard cursor. - * - * The keyboard cursor defaults to using the background color of the - * terminal cell to draw the character at the cursor position. - * - * @param color By default, the widget uses the color of the - * character under the cursor to draw the cursor, and inverts the - * color of that character to make sure it is still readable. If @p - * color is a valid QColor, the widget uses that color to draw the - * character underneath the cursor. If @p color is not an valid QColor, - * the widget falls back to the default behavior. - */ - void setKeyboardCursorTextColor(const QColor &color); - /** * Returns the number of lines of text which can be displayed in the widget. * @@ -219,6 +189,11 @@ public: return _columns; } + int usedColumns() const + { + return _usedColumns; + } + /** * Returns the height of the characters in the font used to draw the text in the display. */ @@ -369,14 +344,79 @@ public: // toggle the header bar Minimize/Maximize button. void setExpandedMode(bool expand); - friend class TerminalPainter; friend class TerminalScrollBar; - TerminalScrollBar *scrollBar() + TerminalScrollBar *scrollBar() const { return _scrollBar; } + qreal opacity() const + { + return _opacity; + } + + QRgb blendColor() const + { + return _blendColor; + } + + bool cursorBlinking() const + { + return _cursorBlinking; + } + + bool textBlinking() const + { + return _textBlinking; + } + + Enum::CursorShapeEnum cursorShape() const + { + return _cursorShape; + } + + bool boldIntense() const + { + return _boldIntense; + } + + bool useFontLineCharacters() const + { + return _useFontLineCharacters; + } + + bool bidiEnabled() const + { + return _bidiEnabled; + } + + int fontAscent() const + { + return _fontAscent; + } + + bool antialiasText() const + { + return _antialiasText; + } + + ColorSchemeWallpaper::Ptr wallpaper() const + { + return _wallpaper; + } + + struct InputMethodData { + QString preeditString; + QRect previousPreeditRect; + }; + + // returns true if the cursor's position is on display. + bool isCursorOnDisplay() const; + + // returns the position of the cursor in columns and lines + QPoint cursorPosition() const; + public Q_SLOTS: /** * Scrolls current ScreenWindow @@ -504,6 +544,8 @@ public Q_SLOTS: void printScreen(); Character getCursorCharacter(int column, int line); + int loc(int x, int y) const; + Q_SIGNALS: void requestToggleExpansion(); /** @@ -547,6 +589,20 @@ Q_SIGNALS: void peekPrimaryRequested(bool doPeek); + void drawContents(Character *image, QPainter &paint, const QRect &rect, bool printerFriendly, int imageSize, bool bidiEnabled, bool &fixedFont, + QVector lineProperties); + void drawCurrentResultRect(QPainter &painter, QRect searchResultRect); + + void highlightScrolledLines(QPainter& painter, QTimer *timer, QRect rect); + QRegion highlightScrolledLinesRegion(bool nothingChanged, QTimer *timer, int &previousScrollCount, QRect &rect, bool &needToClear, int HighlightScrolledLinesWidth); + + void drawBackground(QPainter &painter, const QRect &rect, const QColor &backgroundColor, bool useOpacitySetting); + void drawCursor(QPainter &painter, const QRect &rect, const QColor &foregroundColor, + const QColor &backgroundColor, QColor &characterColor); + void drawCharacters(QPainter &painter, const QRect &rect, const QString &text, + const Character *style, const QColor &characterColor); + void drawInputMethodPreeditString(QPainter &painter, const QRect &rect, TerminalDisplay::InputMethodData &inputMethodData, Character *image); + protected: // events bool event(QEvent *event) override; @@ -634,12 +690,6 @@ private: void setupHeaderVisibility(); - // returns the position of the cursor in columns and lines - QPoint cursorPosition() const; - - // returns true if the cursor's position is on display. - bool isCursorOnDisplay() const; - // redraws the cursor void updateCursor(); @@ -660,8 +710,6 @@ private: // Boilerplate setup for MessageWidget KMessageWidget* createMessageWidget(const QString &text); - int loc(int x, int y) const; - // the window onto the terminal screen which this display // is currently showing. QPointer _screenWindow; @@ -762,18 +810,6 @@ private: Enum::CursorShapeEnum _cursorShape; - // cursor color. If it is invalid (by default) then the foreground - // color of the character under the cursor is used - QColor _cursorColor; - - // cursor text color. If it is invalid (by default) then the background - // color of the character under the cursor is used - QColor _cursorTextColor; - - struct InputMethodData { - QString preeditString; - QRect previousPreeditRect; - }; InputMethodData _inputMethodData; bool _antialiasText; // do we anti-alias or not diff --git a/src/terminalDisplay/TerminalPainter.cpp b/src/terminalDisplay/TerminalPainter.cpp index 3cf8b80f..212ab432 100644 --- a/src/terminalDisplay/TerminalPainter.cpp +++ b/src/terminalDisplay/TerminalPainter.cpp @@ -10,7 +10,6 @@ #include "TerminalPainter.hpp" // Konsole -#include "TerminalDisplay.h" #include "TerminalScrollBar.hpp" #include "ExtendedCharTable.h" #include "../characters/LineBlockCharacters.h" @@ -36,9 +35,20 @@ const QChar LTR_OVERRIDE_CHAR(0x202D); namespace Konsole { - TerminalPainter::TerminalPainter(TerminalDisplay *display) - : _display(display) + TerminalPainter::TerminalPainter(QObject *parent) + : QObject(parent) + , m_cursorColor(QColor()) + , m_cursorTextColor(QColor()) {} + + void TerminalPainter::applyProfile(const Profile::Ptr &profile) + { + // cursor color + // an invalid QColor is used to inform the view widget to + // draw the cursor using the default color( matching the text)7 + m_cursorColor = profile->useCustomCursorColor() ? profile->customCursorColor() : QColor(); + m_cursorTextColor = profile->useCustomCursorColor() ? profile->customCursorTextColor() : QColor(); + } static inline bool isLineCharString(const QString &string) { @@ -60,14 +70,17 @@ namespace Konsole } } - void TerminalPainter::drawContents(QPainter &paint, const QRect &rect, bool printerFriendly) + void TerminalPainter::drawContents(Character *image, QPainter &paint, const QRect &rect, bool printerFriendly, int imageSize, bool bidiEnabled, bool &fixedFont, + QVector lineProperties) { - const int numberOfColumns = _display->_usedColumns; + const auto display = qobject_cast(sender()); + + const int numberOfColumns = display->usedColumns(); QVector univec; univec.reserve(numberOfColumns); for (int y = rect.y(); y <= rect.bottom(); y++) { int x = rect.x(); - if ((_display->_image[_display->loc(rect.x(), y)].character == 0u) && (x != 0)) { + if ((image[display->loc(rect.x(), y)].character == 0u) && (x != 0)) { x--; // Search for start of multi-column character } for (; x <= rect.right(); x++) { @@ -80,10 +93,10 @@ namespace Konsole uint *disstrU = univec.data(); // is this a single character or a sequence of characters ? - if ((_display->_image[_display->loc(x, y)].rendition & RE_EXTENDED_CHAR) != 0) { + if ((image[display->loc(x, y)].rendition & RE_EXTENDED_CHAR) != 0) { // sequence of characters ushort extendedCharLength = 0; - const uint *chars = ExtendedCharTable::instance.lookupExtendedChar(_display->_image[_display->loc(x, y)].character, extendedCharLength); + const uint *chars = ExtendedCharTable::instance.lookupExtendedChar(image[display->loc(x, y)].character, extendedCharLength); if (chars != nullptr) { Q_ASSERT(extendedCharLength > 1); bufferSize += extendedCharLength - 1; @@ -95,39 +108,39 @@ namespace Konsole } } } else { - const uint c = _display->_image[_display->loc(x, y)].character; + const uint c = image[display->loc(x, y)].character; if (c != 0u) { Q_ASSERT(p < bufferSize); disstrU[p++] = c; } } - const bool lineDraw = LineBlockCharacters::canDraw(_display->_image[_display->loc(x, y)].character); - const bool doubleWidth = (_display->_image[qMin(_display->loc(x, y) + 1, _display->_imageSize - 1)].character == 0); - const CharacterColor currentForeground = _display->_image[_display->loc(x, y)].foregroundColor; - const CharacterColor currentBackground = _display->_image[_display->loc(x, y)].backgroundColor; - const RenditionFlags currentRendition = _display->_image[_display->loc(x, y)].rendition; - const QChar::Script currentScript = QChar::script(baseCodePoint(_display->_image[_display->loc(x, y)])); + const bool lineDraw = LineBlockCharacters::canDraw(image[display->loc(x, y)].character); + const bool doubleWidth = (image[qMin(display->loc(x, y) + 1, imageSize - 1)].character == 0); + const CharacterColor currentForeground = image[display->loc(x, y)].foregroundColor; + const CharacterColor currentBackground = image[display->loc(x, y)].backgroundColor; + const RenditionFlags currentRendition = image[display->loc(x, y)].rendition; + const QChar::Script currentScript = QChar::script(baseCodePoint(image[display->loc(x, y)])); const auto isInsideDrawArea = [&](int column) { return column <= rect.right(); }; const auto hasSameColors = [&](int column) { - return _display->_image[_display->loc(column, y)].foregroundColor == currentForeground - && _display->_image[_display->loc(column, y)].backgroundColor == currentBackground; + return image[display->loc(column, y)].foregroundColor == currentForeground + && image[display->loc(column, y)].backgroundColor == currentBackground; }; const auto hasSameRendition = [&](int column) { - return (_display->_image[_display->loc(column, y)].rendition & ~RE_EXTENDED_CHAR) + return (image[display->loc(column, y)].rendition & ~RE_EXTENDED_CHAR) == (currentRendition & ~RE_EXTENDED_CHAR); }; const auto hasSameWidth = [&](int column) { - const int characterLoc = qMin(_display->loc(column, y) + 1, _display->_imageSize - 1); - return (_display->_image[characterLoc].character == 0) == doubleWidth; + const int characterLoc = qMin(display->loc(column, y) + 1, imageSize - 1); + return (image[characterLoc].character == 0) == doubleWidth; }; const auto hasSameLineDrawStatus = [&](int column) { - return LineBlockCharacters::canDraw(_display->_image[_display->loc(column, y)].character) + return LineBlockCharacters::canDraw(image[display->loc(column, y)].character) == lineDraw; }; const auto isSameScript = [&](int column) { - const QChar::Script script = QChar::script(baseCodePoint(_display->_image[_display->loc(column, y)])); + const QChar::Script script = QChar::script(baseCodePoint(image[display->loc(column, y)])); if (currentScript == QChar::Script_Common || script == QChar::Script_Common || currentScript == QChar::Script_Inherited || script == QChar::Script_Inherited) { return true; @@ -135,9 +148,9 @@ namespace Konsole return currentScript == script; }; const auto canBeGrouped = [&](int column) { - return _display->_image[_display->loc(column, y)].character <= 0x7e - || (_display->_image[_display->loc(column, y)].rendition & RE_EXTENDED_CHAR) - || (_display->_bidiEnabled && !doubleWidth); + return image[display->loc(column, y)].character <= 0x7e + || (image[display->loc(column, y)].rendition & RE_EXTENDED_CHAR) + || (bidiEnabled && !doubleWidth); }; if (canBeGrouped(x)) { @@ -145,8 +158,8 @@ namespace Konsole && hasSameRendition(x + len) && hasSameWidth(x + len) && hasSameLineDrawStatus(x + len) && isSameScript(x + len) && canBeGrouped(x + len)) { - const uint c = _display->_image[_display->loc(x + len, y)].character; - if ((_display->_image[_display->loc(x + len, y)].rendition & RE_EXTENDED_CHAR) != 0) { + const uint c = image[display->loc(x + len, y)].character; + if ((image[display->loc(x + len, y)].rendition & RE_EXTENDED_CHAR) != 0) { // sequence of characters ushort extendedCharLength = 0; const uint *chars = ExtendedCharTable::instance.lookupExtendedChar(c, extendedCharLength); @@ -177,33 +190,33 @@ namespace Konsole // Group spaces following any non-wide character with the character. This allows for // rendering ambiguous characters with wide glyphs without clipping them. while (!doubleWidth && isInsideDrawArea(x + len) - && _display->_image[_display->loc(x + len, y)].character == ' ' && hasSameColors(x + len) + && image[display->loc(x + len, y)].character == ' ' && hasSameColors(x + len) && hasSameRendition(x + len)) { // disstrU intentionally not modified - trailing spaces are meaningless len++; } } - if ((x + len < _display->_usedColumns) && (_display->_image[_display->loc(x + len, y)].character == 0u)) { + if ((x + len < display->usedColumns()) && (image[display->loc(x + len, y)].character == 0u)) { len++; // Adjust for trailing part of multi-column character } - const bool save__fixedFont = _display->_fixedFont; + const bool save__fixedFont = fixedFont; if (lineDraw) { - _display->_fixedFont = false; + fixedFont = false; } if (doubleWidth) { - _display->_fixedFont = false; + fixedFont = false; } univec.resize(p); QMatrix textScale; - if (y < _display->_lineProperties.size()) { - if ((_display->_lineProperties[y] & LINE_DOUBLEWIDTH) != 0) { + if (y < lineProperties.size()) { + if ((lineProperties[y] & LINE_DOUBLEWIDTH) != 0) { textScale.scale(2, 1); } - if ((_display->_lineProperties[y] & LINE_DOUBLEHEIGHT) != 0) { + if ((lineProperties[y] & LINE_DOUBLEHEIGHT) != 0) { textScale.scale(1, 2); } } @@ -212,10 +225,10 @@ namespace Konsole paint.setWorldTransform(QTransform(textScale), true); // Calculate the area in which the text will be drawn - QRect textArea = QRect(_display->contentRect().left() + _display->contentsRect().left() + _display->fontWidth() * x, - _display->contentRect().top() + _display->contentsRect().top() + _display->fontHeight() * y, - _display->fontWidth() * len, - _display->fontHeight()); + QRect textArea = QRect(display->contentRect().left() + display->contentsRect().left() + display->fontWidth() * x, + display->contentRect().top() + display->contentsRect().top() + display->fontHeight() * y, + display->fontWidth() * len, + display->fontHeight()); //move the calculated area to take account of scaling applied to the painter. //the position of the area from the origin (0,0) is scaled @@ -232,21 +245,22 @@ namespace Konsole drawPrinterFriendlyTextFragment(paint, textArea, unistr, - &_display->_image[_display->loc(x, y)]); + &image[display->loc(x, y)]); } else { drawTextFragment(paint, textArea, unistr, - &_display->_image[_display->loc(x, y)]); + &image[display->loc(x, y)], + display->colorTable()); } - _display->_fixedFont = save__fixedFont; + fixedFont = save__fixedFont; paint.setWorldTransform(QTransform(textScale.inverted()), true); - if (y < _display->_lineProperties.size() - 1) { + if (y < lineProperties.size() - 1) { - if ((_display->_lineProperties[y] & LINE_DOUBLEHEIGHT) != 0) { + if ((lineProperties[y] & LINE_DOUBLEHEIGHT) != 0) { y++; } } @@ -256,83 +270,85 @@ namespace Konsole } } - void TerminalPainter::drawCurrentResultRect(QPainter &painter) + void TerminalPainter::drawCurrentResultRect(QPainter &painter, QRect searchResultRect) { - if (_display->_screenWindow->currentResultLine() == -1) { + const auto display = qobject_cast(sender()); + + if (display->screenWindow()->currentResultLine() == -1) { return; } - _display->_searchResultRect.setRect(0, _display->contentRect().top() + (_display->_screenWindow->currentResultLine() - _display->_screenWindow->currentLine()) * _display->fontHeight(), - _display->columns() * _display->fontWidth(), _display->fontHeight()); - painter.fillRect(_display->_searchResultRect, QColor(0, 0, 255, 80)); + searchResultRect.setRect(0, display->contentRect().top() + (display->screenWindow()->currentResultLine() - display->screenWindow()->currentLine()) * display->fontHeight(), + display->columns() * display->fontWidth(), display->fontHeight()); + painter.fillRect(searchResultRect, QColor(0, 0, 255, 80)); } - void TerminalPainter::highlightScrolledLines(QPainter& painter) + void TerminalPainter::highlightScrolledLines(QPainter& painter, QTimer *timer, QRect rect) { - if (!_display->_highlightScrolledLinesControl.enabled) { - return; - } + const auto display = qobject_cast(sender()); - QColor color = QColor(_display->_colorTable[Color4Index]); - color.setAlpha(_display->_highlightScrolledLinesControl.timer->isActive() ? 255 : 150); - painter.fillRect(_display->_highlightScrolledLinesControl.rect, color); + QColor color = QColor(display->colorTable()[Color4Index]); + color.setAlpha(timer->isActive() ? 255 : 150); + painter.fillRect(rect, color); } - QRegion TerminalPainter::highlightScrolledLinesRegion(bool nothingChanged) + QRegion TerminalPainter::highlightScrolledLinesRegion(bool nothingChanged, QTimer *timer, int &previousScrollCount, QRect &rect, bool &needToClear, int HighlightScrolledLinesWidth) { + const auto display = qobject_cast(sender()); + QRegion dirtyRegion; - const int highlightLeftPosition = _display->scrollBar()->scrollBarPosition() == Enum::ScrollBarLeft ? _display->scrollBar()->width() : 0; + const int highlightLeftPosition = display->scrollBar()->scrollBarPosition() == Enum::ScrollBarLeft ? display->scrollBar()->width() : 0; int start = 0; - int nb_lines = abs(_display->_screenWindow->scrollCount()); - if (nb_lines > 0 && _display->scrollBar()->maximum() > 0) { + int nb_lines = abs(display->screenWindow()->scrollCount()); + if (nb_lines > 0 && display->scrollBar()->maximum() > 0) { QRect new_highlight; - bool addToCurrentHighlight = _display->_highlightScrolledLinesControl.timer->isActive() && - (_display->_screenWindow->scrollCount() * _display->_highlightScrolledLinesControl.previousScrollCount > 0); + bool addToCurrentHighlight = timer->isActive() && + (display->screenWindow()->scrollCount() * previousScrollCount > 0); if (addToCurrentHighlight) { - if (_display->_screenWindow->scrollCount() > 0) { - start = -1 * (_display->_highlightScrolledLinesControl.previousScrollCount + _display->screenWindow()->scrollCount()) + _display->screenWindow()->windowLines(); + if (display->screenWindow()->scrollCount() > 0) { + start = -1 * (previousScrollCount + display->screenWindow()->scrollCount()) + display->screenWindow()->windowLines(); } else { - start = -1 * _display->_highlightScrolledLinesControl.previousScrollCount; + start = -1 * previousScrollCount; } - _display->_highlightScrolledLinesControl.previousScrollCount += _display->_screenWindow->scrollCount(); + previousScrollCount += display->screenWindow()->scrollCount(); } else { - start = _display->_screenWindow->scrollCount() > 0 ? _display->_screenWindow->windowLines() - nb_lines : 0; - _display->_highlightScrolledLinesControl.previousScrollCount = _display->_screenWindow->scrollCount(); + start = display->screenWindow()->scrollCount() > 0 ? display->screenWindow()->windowLines() - nb_lines : 0; + previousScrollCount = display->screenWindow()->scrollCount(); } - new_highlight.setRect(highlightLeftPosition, _display->contentRect().top() + start * _display->fontHeight(), _display->HIGHLIGHT_SCROLLED_LINES_WIDTH, nb_lines * _display->fontHeight()); - new_highlight.setTop(std::max(new_highlight.top(), _display->contentRect().top())); - new_highlight.setBottom(std::min(new_highlight.bottom(), _display->contentRect().bottom())); + new_highlight.setRect(highlightLeftPosition, display->contentRect().top() + start * display->fontHeight(), HighlightScrolledLinesWidth, nb_lines * display->fontHeight()); + new_highlight.setTop(std::max(new_highlight.top(), display->contentRect().top())); + new_highlight.setBottom(std::min(new_highlight.bottom(), display->contentRect().bottom())); if (!new_highlight.isValid()) { new_highlight = QRect(0, 0, 0, 0); } if (addToCurrentHighlight) { - _display->_highlightScrolledLinesControl.rect |= new_highlight; + rect |= new_highlight; } else { - dirtyRegion |= _display->_highlightScrolledLinesControl.rect; - _display->_highlightScrolledLinesControl.rect = new_highlight; + dirtyRegion |= rect; + rect = new_highlight; } - _display->_highlightScrolledLinesControl.timer->start(); - } else if (!nothingChanged || _display->_highlightScrolledLinesControl.needToClear) { - dirtyRegion = _display->_highlightScrolledLinesControl.rect; - _display->_highlightScrolledLinesControl.rect.setRect(0, 0, 0, 0); - _display->_highlightScrolledLinesControl.needToClear = false; + timer->start(); + } else if (!nothingChanged || needToClear) { + dirtyRegion = rect; + rect.setRect(0, 0, 0, 0); + needToClear = false; } return dirtyRegion; } void TerminalPainter::drawTextFragment(QPainter &painter, const QRect &rect, const QString &text, - const Character *style) + const Character *style, const ColorEntry *colorTable) { // setup painter - const QColor foregroundColor = style->foregroundColor.color(_display->_colorTable); - const QColor backgroundColor = style->backgroundColor.color(_display->_colorTable); + const QColor foregroundColor = style->foregroundColor.color(colorTable); + const QColor backgroundColor = style->backgroundColor.color(colorTable); - if (backgroundColor != _display->_colorTable[DEFAULT_BACK_COLOR]) { + if (backgroundColor != colorTable[DEFAULT_BACK_COLOR]) { drawBackground(painter, rect, backgroundColor, false); } @@ -358,16 +374,18 @@ namespace Konsole void TerminalPainter::drawBackground(QPainter &painter, const QRect &rect, const QColor &backgroundColor, bool useOpacitySetting) { - if (useOpacitySetting && !_display->_wallpaper->isNull() && - _display->_wallpaper->draw(painter, rect, _display->_opacity)) { - } else if (qAlpha(_display->_blendColor) < 0xff && useOpacitySetting) { + const auto display = qobject_cast(sender()); + + if (useOpacitySetting && !display->wallpaper()->isNull() && + display->wallpaper()->draw(painter, rect, display->opacity())) { + } else if (qAlpha(display->blendColor()) < 0xff && useOpacitySetting) { #if defined(Q_OS_MACOS) // TODO: On MacOS, using CompositionMode doesn't work. Altering the // transparency in the color scheme alters the brightness. painter.fillRect(rect, backgroundColor); #else QColor color(backgroundColor); - color.setAlpha(qAlpha(_display->_blendColor)); + color.setAlpha(qAlpha(display->blendColor())); const QPainter::CompositionMode originalMode = painter.compositionMode(); painter.setCompositionMode(QPainter::CompositionMode_Source); @@ -382,38 +400,40 @@ namespace Konsole void TerminalPainter::drawCursor(QPainter &painter, const QRect &rect, const QColor &foregroundColor, const QColor &backgroundColor, QColor &characterColor) { - if (_display->_cursorBlinking) { + const auto display = qobject_cast(sender()); + + if (display->cursorBlinking()) { return; } QRectF cursorRect = rect.adjusted(0, 1, 0, 0); - QColor cursorColor = _display->_cursorColor.isValid() ? _display->_cursorColor : foregroundColor; + QColor cursorColor = m_cursorColor.isValid() ? m_cursorColor : foregroundColor; QPen pen(cursorColor); // TODO: the relative pen width to draw the cursor is a bit hacky // and set to 1/12 of the font width. Visually it seems to work at // all scales but there must be better ways to do it - const qreal width = qMax(_display->fontWidth() / 12.0, 1.0); + const qreal width = qMax(display->fontWidth() / 12.0, 1.0); const qreal halfWidth = width / 2.0; pen.setWidthF(width); painter.setPen(pen); - if (_display->_cursorShape == Enum::BlockCursor) { + if (display->cursorShape() == Enum::BlockCursor) { painter.drawRect(cursorRect.adjusted(halfWidth, halfWidth, -halfWidth, -halfWidth)); - if (_display->hasFocus()) { + if (display->hasFocus()) { painter.fillRect(cursorRect, cursorColor); - characterColor = _display->_cursorTextColor.isValid() ? _display->_cursorTextColor : backgroundColor; + characterColor = m_cursorTextColor.isValid() ? m_cursorTextColor : backgroundColor; } - } else if (_display->_cursorShape == Enum::UnderlineCursor) { + } else if (display->cursorShape() == Enum::UnderlineCursor) { QLineF line(cursorRect.left() + halfWidth, cursorRect.bottom() - halfWidth, cursorRect.right() - halfWidth, cursorRect.bottom() - halfWidth); painter.drawLine(line); - } else if (_display->_cursorShape == Enum::IBeamCursor) { + } else if (display->cursorShape() == Enum::IBeamCursor) { QLineF line(cursorRect.left() + halfWidth, cursorRect.top() + halfWidth, cursorRect.left() + halfWidth, @@ -425,7 +445,9 @@ namespace Konsole void TerminalPainter::drawCharacters(QPainter &painter, const QRect &rect, const QString &text, const Character *style, const QColor &characterColor) { - if (_display->_textBlinking && ((style->rendition & RE_BLINK) != 0)) { + const auto display = qobject_cast(sender()); + + if (display->textBlinking() && ((style->rendition & RE_BLINK) != 0)) { return; } @@ -435,17 +457,17 @@ namespace Konsole static constexpr int MaxFontWeight = 99; - const int normalWeight = _display->font().weight(); + const int normalWeight = display->font().weight(); const int boldWeight = qMin(normalWeight + 26, MaxFontWeight); const auto isBold = [boldWeight](const QFont &font) { return font.weight() >= boldWeight; }; - const bool useBold = (((style->rendition & RE_BOLD) != 0) && _display->_boldIntense); - const bool useUnderline = ((style->rendition & RE_UNDERLINE) != 0) || _display->font().underline(); - const bool useItalic = ((style->rendition & RE_ITALIC) != 0) || _display->font().italic(); - const bool useStrikeOut = ((style->rendition & RE_STRIKEOUT) != 0) || _display->font().strikeOut(); - const bool useOverline = ((style->rendition & RE_OVERLINE) != 0) || _display->font().overline(); + const bool useBold = (((style->rendition & RE_BOLD) != 0) && display->boldIntense()); + const bool useUnderline = ((style->rendition & RE_UNDERLINE) != 0) || display->font().underline(); + const bool useItalic = ((style->rendition & RE_ITALIC) != 0) || display->font().italic(); + const bool useStrikeOut = ((style->rendition & RE_STRIKEOUT) != 0) || display->font().strikeOut(); + const bool useOverline = ((style->rendition & RE_OVERLINE) != 0) || display->font().overline(); QFont currentFont = painter.font(); @@ -464,7 +486,7 @@ namespace Konsole } // setup pen - const QColor foregroundColor = style->foregroundColor.color(_display->_colorTable); + const QColor foregroundColor = style->foregroundColor.color(display->colorTable()); const QColor color = characterColor.isValid() ? characterColor : foregroundColor; QPen pen = painter.pen(); if (pen.color() != color) { @@ -476,53 +498,54 @@ namespace Konsole const auto origClipRegion = painter.clipRegion(); painter.setClipRect(rect); // draw text - if (isLineCharString(text) && !_display->_useFontLineCharacters) { - drawLineCharString(painter, rect.x(), rect.y(), text, style); + if (isLineCharString(text) && !display->useFontLineCharacters()) { + drawLineCharString(display, painter, rect.x(), rect.y(), text, style); } else { painter.setLayoutDirection(Qt::LeftToRight); - if (_display->_bidiEnabled) { - painter.drawText(rect.x(), rect.y() + _display->_fontAscent + _display->lineSpacing(), text); + if (display->bidiEnabled()) { + painter.drawText(rect.x(), rect.y() + display->fontAscent() + display->lineSpacing(), text); } else { - painter.drawText(rect.x(), rect.y() + _display->_fontAscent + _display->lineSpacing(), LTR_OVERRIDE_CHAR + text); + painter.drawText(rect.x(), rect.y() + display->fontAscent() + display->lineSpacing(), LTR_OVERRIDE_CHAR + text); } } painter.setClipRegion(origClipRegion); painter.setClipping(origClipping); } - void TerminalPainter::drawLineCharString(QPainter &painter, int x, int y, const QString &str, - const Character *attributes) + void TerminalPainter::drawLineCharString(TerminalDisplay *display, QPainter &painter, int x, int y, const QString &str, const Character *attributes) { - painter.setRenderHint(QPainter::Antialiasing, _display->_antialiasText); + painter.setRenderHint(QPainter::Antialiasing, display->antialiasText()); - const bool useBoldPen = (attributes->rendition & RE_BOLD) != 0 && _display->_boldIntense; + const bool useBoldPen = (attributes->rendition & RE_BOLD) != 0 && display->boldIntense(); - QRect cellRect = {x, y, _display->fontWidth(), _display->fontHeight()}; + QRect cellRect = {x, y, display->fontWidth(), display->fontHeight()}; for (int i = 0; i < str.length(); i++) { - LineBlockCharacters::draw(painter, cellRect.translated(i * _display->fontWidth(), 0), str[i], useBoldPen); + LineBlockCharacters::draw(painter, cellRect.translated(i * display->fontWidth(), 0), str[i], useBoldPen); } painter.setRenderHint(QPainter::Antialiasing, false); } - void TerminalPainter::drawInputMethodPreeditString(QPainter &painter, const QRect &rect) + void TerminalPainter::drawInputMethodPreeditString(QPainter &painter, const QRect &rect, TerminalDisplay::InputMethodData &inputMethodData, Character *image) { - if (_display->_inputMethodData.preeditString.isEmpty() || !_display->isCursorOnDisplay()) { + const auto display = qobject_cast(sender()); + + if (inputMethodData.preeditString.isEmpty() || !display->isCursorOnDisplay()) { return; } - const QPoint cursorPos = _display->cursorPosition(); + const QPoint cursorPos = display->cursorPosition(); QColor characterColor; - const QColor background = _display->_colorTable[DEFAULT_BACK_COLOR]; - const QColor foreground = _display->_colorTable[DEFAULT_FORE_COLOR]; - const Character *style = &_display->_image[_display->loc(cursorPos.x(), cursorPos.y())]; + const QColor background = display->colorTable()[DEFAULT_BACK_COLOR]; + const QColor foreground = display->colorTable()[DEFAULT_FORE_COLOR]; + const Character *style = &image[display->loc(cursorPos.x(), cursorPos.y())]; drawBackground(painter, rect, background, true); drawCursor(painter, rect, foreground, background, characterColor); - drawCharacters(painter, rect, _display->_inputMethodData.preeditString, style, characterColor); + drawCharacters(painter, rect, inputMethodData.preeditString, style, characterColor); - _display->_inputMethodData.previousPreeditRect = rect; + inputMethodData.previousPreeditRect = rect; } } diff --git a/src/terminalDisplay/TerminalPainter.hpp b/src/terminalDisplay/TerminalPainter.hpp index da9c92c3..2b1b0c0e 100644 --- a/src/terminalDisplay/TerminalPainter.hpp +++ b/src/terminalDisplay/TerminalPainter.hpp @@ -20,6 +20,8 @@ #include "ScreenWindow.h" #include "Enumeration.h" #include "colorscheme/ColorSchemeWallpaper.h" +#include "profile/Profile.h" +#include "terminalDisplay/TerminalDisplay.h" class QRect; class QColor; @@ -34,55 +36,68 @@ namespace Konsole class Character; class TerminalDisplay; - class TerminalPainter + class TerminalPainter : public QObject { public: - explicit TerminalPainter(TerminalDisplay *display); + explicit TerminalPainter(QObject *parent = nullptr); ~TerminalPainter() = default; + void applyProfile(const Profile::Ptr &profile); + // -- Drawing helpers -- // divides the part of the display specified by 'rect' into // fragments according to their colors and styles and calls // drawTextFragment() or drawPrinterFriendlyTextFragment() // to draw the fragments - void drawContents(QPainter &paint, const QRect &rect, bool PrinterFriendly); + void drawContents(Character *image, QPainter &paint, const QRect &rect, bool PrinterFriendly, int imageSize, bool bidiEnabled, bool &fixedFont, + QVector lineProperties); + // draw a transparent rectangle over the line of the current match - void drawCurrentResultRect(QPainter &painter); + void drawCurrentResultRect(QPainter &painter, QRect searchResultRect); + // draw a thin highlight on the left of the screen for lines that have been scrolled into view - void highlightScrolledLines(QPainter& painter); - // compute which region need to be repainted for scrolled lines highlight - QRegion highlightScrolledLinesRegion(bool nothingChanged); + void highlightScrolledLines(QPainter& painter, QTimer *timer, QRect rect); - // draws a section of text, all the text in this section - // has a common color and style - void drawTextFragment(QPainter &painter, const QRect &rect, const QString &text, - const Character *style); + // compute which region need to be repainted for scrolled lines highlight + QRegion highlightScrolledLinesRegion(bool nothingChanged, QTimer *timer, int &previousScrollCount, QRect &rect, bool &needToClear, int HighlightScrolledLinesWidth); - void drawPrinterFriendlyTextFragment(QPainter &painter, const QRect &rect, const QString &text, - const Character *style); // draws the background for a text fragment // if useOpacitySetting is true then the color's alpha value will be set to // the display's transparency (set with setOpacity()), otherwise the background // will be drawn fully opaque void drawBackground(QPainter &painter, const QRect &rect, const QColor &backgroundColor, bool useOpacitySetting); + // draws the cursor character void drawCursor(QPainter &painter, const QRect &rect, const QColor &foregroundColor, const QColor &backgroundColor, QColor &characterColor); // draws the characters or line graphics in a text fragment void drawCharacters(QPainter &painter, const QRect &rect, const QString &text, const Character *style, const QColor &characterColor); - // draws a string of line graphics - void drawLineCharString(QPainter &painter, int x, int y, const QString &str, - const Character *attributes); // draws the preedit string for input methods - void drawInputMethodPreeditString(QPainter &painter, const QRect &rect); + void drawInputMethodPreeditString(QPainter &painter, const QRect &rect, TerminalDisplay::InputMethodData &inputMethodData, Character *image); private: + // draws a string of line graphics + void drawLineCharString(TerminalDisplay *display, QPainter &painter, int x, int y, const QString &str, const Character *attributes); + + // draws a section of text, all the text in this section + // has a common color and style + void drawTextFragment(QPainter &painter, const QRect &rect, const QString &text, + const Character *style, const ColorEntry *colorTable); + + void drawPrinterFriendlyTextFragment(QPainter &painter, const QRect &rect, const QString &text, + const Character *style); + + // cursor color. If it is invalid (by default) then the foreground + // color of the character under the cursor is used + QColor m_cursorColor; - TerminalDisplay *_display; + // cursor text color. If it is invalid (by default) then the background + // color of the character under the cursor is used + QColor m_cursorTextColor; }; }