diff --git a/src/EditProfileAppearancePage.ui b/src/EditProfileAppearancePage.ui --- a/src/EditProfileAppearancePage.ui +++ b/src/EditProfileAppearancePage.ui @@ -312,61 +312,101 @@ - + + + + 0 + 0 + + + + Use a custom, fixed color for the cursor + + + Custom cursor color + + + cursorColor + + + + + - 0 + 6 - - - - - 0 - 0 - + + + + Qt::Horizontal - - Use a custom, fixed color for the cursor + + QSizePolicy::Fixed + + + + 24 + 20 + + + + + - Custom cursor color: + Cursor color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + customColorSelectButton - - cursorColor - - + - - - 0 - 0 - - Select the color used to draw the cursor - - - - + Qt::Horizontal - 0 - 0 + 40 + 20 + + + + Text color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + customTextColorSelectButton + + + + + + + Select the color used to draw the character underneath the cursor + + + - + Qt::Vertical @@ -382,7 +422,7 @@ - + Blinking: @@ -392,7 +432,7 @@ - + @@ -680,6 +720,7 @@ autoCursorColorButton customCursorColorButton customColorSelectButton + customTextColorSelectButton enableBlinkingCursorButton lineSpacingSpinner marginsSpinner diff --git a/src/EditProfileDialog.h b/src/EditProfileDialog.h --- a/src/EditProfileDialog.h +++ b/src/EditProfileDialog.h @@ -149,6 +149,7 @@ void autoCursorColor(); void customCursorColor(); void customCursorColorChanged(const QColor &); + void customCursorTextColorChanged(const QColor &); void terminalMarginChanged(int margin); void lineSpacingChanged(int); void setTerminalCenter(bool enable); diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -722,16 +722,12 @@ } _appearanceUi->customColorSelectButton->setColor(profile->customCursorColor()); + _appearanceUi->customTextColorSelectButton->setColor(profile->customCursorTextColor()); connect(_appearanceUi->customCursorColorButton, &QRadioButton::clicked, this, &Konsole::EditProfileDialog::customCursorColor); connect(_appearanceUi->autoCursorColorButton, &QRadioButton::clicked, this, &Konsole::EditProfileDialog::autoCursorColor); connect(_appearanceUi->customColorSelectButton, &KColorButton::changed, this, &Konsole::EditProfileDialog::customCursorColorChanged); - - // Make radio buttons height equal - int cursorColorRadioHeight = qMax(_appearanceUi->autoCursorColorButton->minimumSizeHint().height(), - _appearanceUi->customColorSelectButton->minimumSizeHint().height()); - _appearanceUi->autoCursorColorButton->setMinimumHeight(cursorColorRadioHeight); - _appearanceUi->customCursorColorButton->setMinimumHeight(cursorColorRadioHeight); + connect(_appearanceUi->customTextColorSelectButton, &KColorButton::changed, this, &Konsole::EditProfileDialog::customCursorTextColorChanged); const ButtonGroupOptions cursorShapeOptions = { _appearanceUi->cursorShape, // group @@ -822,6 +818,15 @@ _appearanceUi->customCursorColorButton->click(); } +void EditProfileDialog::customCursorTextColorChanged(const QColor &color) +{ + preview(Profile::CustomCursorTextColor, color); + updateTempProfileProperty(Profile::CustomCursorTextColor, color); + + // ensure that custom cursor colors are enabled + _appearanceUi->customCursorColorButton->click(); +} + void EditProfileDialog::terminalMarginChanged(int margin) { preview(Profile::TerminalMargin, margin); diff --git a/src/Profile.h b/src/Profile.h --- a/src/Profile.h +++ b/src/Profile.h @@ -186,6 +186,11 @@ * Only applicable if the UseCustomCursorColor property is true. */ CustomCursorColor, + /** (QColor) The color used by terminal displays to draw the character + * underneath the cursor. Only applicable if the UseCustomCursorColor + * property is true and CursorShape property is Enum::BlockCursor. + */ + CustomCursorTextColor, /** (QString) A string consisting of the characters used to delimit * words when selecting text in the terminal display. */ @@ -524,12 +529,18 @@ return property(Profile::UseCustomCursorColor); } - /** Convenience method for property(Profile::CustomCursorColor) */ + /** Convenience method for property(Profile::CustomCursorColor) */ QColor customCursorColor() const { return property(Profile::CustomCursorColor); } + /** Convenience method for property(Profile::CustomCursorTextColor) */ + QColor customCursorTextColor() const + { + return property(Profile::CustomCursorTextColor); + } + /** Convenience method for property(Profile::WordCharacters) */ QString wordCharacters() const { diff --git a/src/Profile.cpp b/src/Profile.cpp --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -106,6 +106,7 @@ , { UseCustomCursorColor , "UseCustomCursorColor" , CURSOR_GROUP , QVariant::Bool} , { CursorShape , "CursorShape" , CURSOR_GROUP , QVariant::Int} , { CustomCursorColor , "CustomCursorColor" , CURSOR_GROUP , QVariant::Color } + , { CustomCursorTextColor , "CustomCursorTextColor" , CURSOR_GROUP , QVariant::Color } // Interaction , { WordCharacters , "WordCharacters" , INTERACTION_GROUP , QVariant::String } @@ -210,7 +211,8 @@ setProperty(LineSpacing, 0); setProperty(CursorShape, Enum::BlockCursor); setProperty(UseCustomCursorColor, false); - setProperty(CustomCursorColor, QColor(Qt::black)); + setProperty(CustomCursorColor, QColor(Qt::white)); + setProperty(CustomCursorTextColor, QColor(Qt::black)); setProperty(BellMode, Enum::NotifyBell); setProperty(DefaultEncoding, QLatin1String(QTextCodec::codecForLocale()->name())); diff --git a/src/TerminalDisplay.h b/src/TerminalDisplay.h --- a/src/TerminalDisplay.h +++ b/src/TerminalDisplay.h @@ -203,6 +203,21 @@ */ 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. * @@ -630,10 +645,10 @@ bool useOpacitySetting); // draws the cursor character void drawCursor(QPainter &painter, const QRect &rect, const QColor &foregroundColor, - const QColor &backgroundColor, bool &invertCharacterColor); + 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, bool invertCharacterColor); + 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); @@ -818,6 +833,10 @@ // 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; diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -479,6 +479,7 @@ , _filterUpdateRequired(true) , _cursorShape(Enum::BlockCursor) , _cursorColor(QColor()) + , _cursorTextColor(QColor()) , _antialiasText(true) , _useFontLineCharacters(false) , _printerFriendly(false) @@ -667,6 +668,11 @@ _cursorColor = color; } +void TerminalDisplay::setKeyboardCursorTextColor(const QColor& color) +{ + _cursorTextColor = color; +} + void TerminalDisplay::setOpacity(qreal opacity) { QColor color(_blendColor); @@ -716,8 +722,8 @@ void TerminalDisplay::drawCursor(QPainter& painter, const QRect& rect, const QColor& foregroundColor, - const QColor& /*backgroundColor*/, - bool& invertCharacterColor) + const QColor& backgroundColor, + QColor& characterColor) { // don't draw cursor which is currently blinking if (_cursorBlinking) { @@ -744,11 +750,10 @@ if (hasFocus()) { painter.fillRect(cursorRect, cursorColor); - if (!_cursorColor.isValid()) { - // invert the color used to draw the text to ensure that the character at - // the cursor position is readable - invertCharacterColor = true; - } + // if the cursor text color is valid then use it to draw the character under the cursor, + // otherwise invert the color used to draw the text to ensure that the character at + // the cursor position is readable + characterColor = _cursorTextColor.isValid() ? _cursorTextColor : backgroundColor; } } else if (_cursorShape == Enum::UnderlineCursor) { QLineF line(cursorRect.left() + 0.5, @@ -770,7 +775,7 @@ const QRect& rect, const QString& text, const Character* style, - bool invertCharacterColor) + const QColor& characterColor) { // don't draw text which is currently blinking if (_textBlinking && ((style->rendition & RE_BLINK) != 0)) { @@ -813,8 +818,8 @@ } // setup pen - const CharacterColor& textColor = (invertCharacterColor ? style->backgroundColor : style->foregroundColor); - const QColor color = textColor.color(_colorTable); + const QColor foregroundColor = style->foregroundColor.color(_colorTable); + const QColor color = characterColor.isValid() ? characterColor : foregroundColor; QPen pen = painter.pen(); if (pen.color() != color) { pen.setColor(color); @@ -861,13 +866,13 @@ // draw cursor shape if the current character is the cursor // this may alter the foreground and background colors - bool invertCharacterColor = false; + QColor characterColor; if ((style->rendition & RE_CURSOR) != 0) { - drawCursor(painter, rect, foregroundColor, backgroundColor, invertCharacterColor); + drawCursor(painter, rect, foregroundColor, backgroundColor, characterColor); } // draw text - drawCharacters(painter, rect, text, style, invertCharacterColor); + drawCharacters(painter, rect, text, style, characterColor); } void TerminalDisplay::drawPrinterFriendlyTextFragment(QPainter& painter, @@ -882,7 +887,7 @@ print_style.backgroundColor = CharacterColor(COLOR_SPACE_RGB, 0xFFFFFFFF); // draw text - drawCharacters(painter, rect, text, &print_style, false); + drawCharacters(painter, rect, text, &print_style, QColor()); } void TerminalDisplay::setRandomSeed(uint randomSeed) @@ -3435,14 +3440,14 @@ const QPoint cursorPos = cursorPosition(); - bool invertColors = false; + QColor characterColor; const QColor background = _colorTable[DEFAULT_BACK_COLOR]; const QColor foreground = _colorTable[DEFAULT_FORE_COLOR]; const Character* style = &_image[loc(cursorPos.x(), cursorPos.y())]; drawBackground(painter, rect, background, true); - drawCursor(painter, rect, foreground, background, invertColors); - drawCharacters(painter, rect, _inputMethodData.preeditString, style, invertColors); + drawCursor(painter, rect, foreground, background, characterColor); + drawCharacters(painter, rect, _inputMethodData.preeditString, style, characterColor); _inputMethodData.previousPreeditRect = rect; } @@ -4007,6 +4012,7 @@ // 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()); diff --git a/src/autotests/ProfileTest.cpp b/src/autotests/ProfileTest.cpp --- a/src/autotests/ProfileTest.cpp +++ b/src/autotests/ProfileTest.cpp @@ -43,9 +43,11 @@ parent->setProperty(Profile::UseCustomCursorColor, true); QVERIFY(parent->useCustomCursorColor()); QCOMPARE(parent->customCursorColor(), QColor()); + QCOMPARE(parent->customCursorTextColor(), QColor()); parent->setProperty(Profile::UseCustomCursorColor, false); QVERIFY(!parent->useCustomCursorColor()); QCOMPARE(parent->customCursorColor(), QColor()); + QCOMPARE(parent->customCursorTextColor(), QColor()); // create a child profile Profile *child = new Profile(Profile::Ptr(parent));