Commit a7f23d21 authored by Arthur Kasimov's avatar Arthur Kasimov
Browse files

Add an option to set the custom color of text under the cursor

Current version of Konsole allows to select the custom color of the
cursor (Settings -> Edit Current Profile -> Appearance -> Cursor ->
Custom cursor color). This works well for I-Beam and Underline cursor
shapes. But for block-shaped cursors the text under the cursor is often
hard to read, e.g. bright text under the bright cursor or dark text
under the dark cursor.

This patch adds an ability to select the custom color of the character
under the cursor. The character uses this color only when the cursor
shape is Block and Konsole window is focused. Otherwise the character
uses its foreground color as usual.

FEATURE: 407915
FIXED-IN: 20.04
parent e5b2ada1
......@@ -312,61 +312,101 @@
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="customColorLayout">
<widget class="QRadioButton" name="customCursorColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Use a custom, fixed color for the cursor</string>
</property>
<property name="text">
<string>Custom cursor color</string>
</property>
<attribute name="buttonGroup">
<string notr="true">cursorColor</string>
</attribute>
</widget>
</item>
<item row="6" column="1">
<layout class="QGridLayout" name="customColorLayout">
<property name="spacing">
<number>0</number>
<number>6</number>
</property>
<item>
<widget class="QRadioButton" name="customCursorColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="0" column="0">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="toolTip">
<string>Use a custom, fixed color for the cursor</string>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>24</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="customCursorColorLabel">
<property name="text">
<string>Custom cursor color:</string>
<string>Cursor:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>customColorSelectButton</cstring>
</property>
<attribute name="buttonGroup">
<string notr="true">cursorColor</string>
</attribute>
</widget>
</item>
<item>
<item row="0" column="2">
<widget class="KColorButton" name="customColorSelectButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Select the color used to draw the cursor</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<item row="0" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLabel" name="customCursorTextColorLabel">
<property name="text">
<string>Text:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>customTextColorSelectButton</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="KColorButton" name="customTextColorSelectButton">
<property name="toolTip">
<string>Select the color used to draw the character underneath the cursor</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="1">
<item row="7" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -382,7 +422,7 @@
</property>
</spacer>
</item>
<item row="7" column="0" alignment="Qt::AlignRight|Qt::AlignVCenter">
<item row="8" column="0" alignment="Qt::AlignRight|Qt::AlignVCenter">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Blinking:</string>
......@@ -392,7 +432,7 @@
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QCheckBox" name="enableBlinkingCursorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
......@@ -680,6 +720,7 @@
<tabstop>autoCursorColorButton</tabstop>
<tabstop>customCursorColorButton</tabstop>
<tabstop>customColorSelectButton</tabstop>
<tabstop>customTextColorSelectButton</tabstop>
<tabstop>enableBlinkingCursorButton</tabstop>
<tabstop>lineSpacingSpinner</tabstop>
<tabstop>marginsSpinner</tabstop>
......
......@@ -722,16 +722,12 @@ void EditProfileDialog::setupAppearancePage(const Profile::Ptr &profile)
}
_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 @@ void EditProfileDialog::customCursorColorChanged(const QColor &color)
_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);
......
......@@ -149,6 +149,7 @@ private Q_SLOTS:
void autoCursorColor();
void customCursorColor();
void customCursorColorChanged(const QColor &);
void customCursorTextColorChanged(const QColor &);
void terminalMarginChanged(int margin);
void lineSpacingChanged(int);
void setTerminalCenter(bool enable);
......
......@@ -106,6 +106,7 @@ const Profile::PropertyInfo Profile::DefaultPropertyNames[] = {
, { 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 @@ void Profile::useFallback()
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()));
......
......@@ -186,6 +186,11 @@ public:
* 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 @@ public:
return property<bool>(Profile::UseCustomCursorColor);
}
/** Convenience method for property<bool>(Profile::CustomCursorColor) */
/** Convenience method for property<QColor>(Profile::CustomCursorColor) */
QColor customCursorColor() const
{
return property<QColor>(Profile::CustomCursorColor);
}
/** Convenience method for property<QColor>(Profile::CustomCursorTextColor) */
QColor customCursorTextColor() const
{
return property<QColor>(Profile::CustomCursorTextColor);
}
/** Convenience method for property<QString>(Profile::WordCharacters) */
QString wordCharacters() const
{
......
......@@ -479,6 +479,7 @@ TerminalDisplay::TerminalDisplay(QWidget* parent)
, _filterUpdateRequired(true)
, _cursorShape(Enum::BlockCursor)
, _cursorColor(QColor())
, _cursorTextColor(QColor())
, _antialiasText(true)
, _useFontLineCharacters(false)
, _printerFriendly(false)
......@@ -667,6 +668,11 @@ void TerminalDisplay::setKeyboardCursorColor(const QColor& color)
_cursorColor = color;
}
void TerminalDisplay::setKeyboardCursorTextColor(const QColor& color)
{
_cursorTextColor = color;
}
void TerminalDisplay::setOpacity(qreal opacity)
{
QColor color(_blendColor);
......@@ -716,8 +722,8 @@ void TerminalDisplay::drawBackground(QPainter& painter, const QRect& rect, const
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 @@ void TerminalDisplay::drawCursor(QPainter& painter,
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 @@ void TerminalDisplay::drawCharacters(QPainter& painter,
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 @@ void TerminalDisplay::drawCharacters(QPainter& painter,
}
// 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 @@ void TerminalDisplay::drawTextFragment(QPainter& painter ,
// 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 @@ void TerminalDisplay::drawPrinterFriendlyTextFragment(QPainter& painter,
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 @@ void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRe
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 @@ void TerminalDisplay::applyProfile(const Profile::Ptr &profile)
// 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());
......
......@@ -203,6 +203,21 @@ public:
*/
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 @@ private:
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 @@ private:
// 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;
......
......@@ -43,9 +43,11 @@ void ProfileTest::testProfile()
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));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment