[utilities/konsole] src: Add right-click paste feature
Matej Kovac
null at kde.org
Thu Jun 4 17:29:32 BST 2026
Git commit da11737e4d17d3696f6a3f5920dc711a935883af by Matej Kovac.
Committed on 04/06/2026 at 15:37.
Pushed by tcanabrava into branch 'master'.
Add right-click paste feature
The mouse wheel is often tedious to click, but right-click is easy.
Already used in many terminals (e.g. Putty), switching between those
supports muscle memory.
If enabled, and right-click is used for pasting, the context-menu
can be displayed by pressing Control key + right-click.
FEATURE: 497675
FEATURE: 519241
GUI: new options in profile controling right-click behavior in Konsole
M +10 -0 src/Enumeration.h
M +1 -0 src/profile/Profile.cpp
M +16 -0 src/profile/Profile.h
M +24 -9 src/terminalDisplay/TerminalDisplay.cpp
M +2 -0 src/terminalDisplay/TerminalDisplay.h
M +24 -0 src/widgets/EditProfileDialog.cpp
M +3 -0 src/widgets/EditProfileDialog.h
M +71 -5 src/widgets/EditProfileMousePage.ui
https://invent.kde.org/utilities/konsole/-/commit/da11737e4d17d3696f6a3f5920dc711a935883af
diff --git a/src/Enumeration.h b/src/Enumeration.h
index a1aa23063..d85b1c4c5 100644
--- a/src/Enumeration.h
+++ b/src/Enumeration.h
@@ -97,6 +97,16 @@ public:
PasteFromClipboard = 1,
};
+ /** This enum describes the source from which mouse right click pastes data . */
+ enum RightClickPasteModeEnum {
+ /** Right-click paste is disabled. */
+ RightClickPasteDisabled = 0,
+ /** Paste from X11 Selection. */
+ RightClickPasteFromX11Selection = 1,
+ /** Paste from Clipboard. */
+ RightClickPasteFromClipboard = 2,
+ };
+
/**
* This enum describes the text editor cmd used to open local text file URLs
* in Konsole, where line and column data are appended to the file URL, e.g.:
diff --git a/src/profile/Profile.cpp b/src/profile/Profile.cpp
index 2f91b9960..07d4b703e 100644
--- a/src/profile/Profile.cpp
+++ b/src/profile/Profile.cpp
@@ -176,6 +176,7 @@ const std::vector<Profile::PropertyInfo> Profile::DefaultProperties = {
{PasteFromSelectionEnabled, "PasteFromSelectionEnabled", INTERACTION_GROUP, true},
{PasteFromClipboardEnabled, "PasteFromClipboardEnabled", INTERACTION_GROUP, false},
{MiddleClickPasteMode, "MiddleClickPasteMode", INTERACTION_GROUP, Enum::PasteFromX11Selection},
+ {RightClickPasteMode, "RightClickPasteMode", INTERACTION_GROUP, Enum::RightClickPasteDisabled},
{MouseWheelZoomEnabled, "MouseWheelZoomEnabled", INTERACTION_GROUP, true},
{AllowMouseTracking, "AllowMouseTracking", INTERACTION_GROUP, true},
{AlternateScrolling, "AlternateScrolling", INTERACTION_GROUP, true},
diff --git a/src/profile/Profile.h b/src/profile/Profile.h
index e33c8c9bb..eee0aa0f1 100644
--- a/src/profile/Profile.h
+++ b/src/profile/Profile.h
@@ -277,6 +277,12 @@ public:
* See Enum::MiddleClickPasteModeEnum
*/
MiddleClickPasteMode,
+ /** (RightClickPasteModeEnum) Specifies the source from which mouse
+ * right click pastes data.
+ *
+ * See Enum::RightClickPasteModeEnum
+ */
+ RightClickPasteMode,
/** (String) Default text codec */
DefaultEncoding,
/** (bool) Whether fonts should be aliased or not */
@@ -1012,6 +1018,16 @@ public:
return property<bool>(Profile::FontHinting);
}
+ Enum::MiddleClickPasteModeEnum middleClickPasteMode() const
+ {
+ return static_cast<Enum::MiddleClickPasteModeEnum>(property<int>(Profile::MiddleClickPasteMode));
+ }
+
+ Enum::RightClickPasteModeEnum rightClickPasteMode() const
+ {
+ return static_cast<Enum::RightClickPasteModeEnum>(property<int>(Profile::RightClickPasteMode));
+ }
+
/** Return a list of all properties names and their type
* (for use with -p option).
*/
diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp
index e1f751ea1..802235c83 100644
--- a/src/terminalDisplay/TerminalDisplay.cpp
+++ b/src/terminalDisplay/TerminalDisplay.cpp
@@ -829,7 +829,7 @@ void TerminalDisplay::drawBadge(QPainter &painter)
}
QString badgeText = session->badgeText();
-
+
// Don't draw if badge text is empty
if (badgeText.isEmpty()) {
return;
@@ -846,11 +846,11 @@ void TerminalDisplay::drawBadge(QPainter &painter)
if (!badgeColor.isValid()) {
badgeColor = QColor(255, 255, 255); // Default white
}
-
+
if (badgeFontFamily.isEmpty()) {
badgeFontFamily = _terminalFont->getVTFont().family(); // Use terminal font family as default
}
-
+
if (badgeFontSize <= 0) {
badgeFontSize = qMax(12, _terminalFont->fontHeight() * 3 / 4); // Default to 3/4 of terminal font height, minimum 12
}
@@ -862,7 +862,7 @@ void TerminalDisplay::drawBadge(QPainter &painter)
// Calculate text metrics
QFontMetrics fontMetrics(badgeFont);
QRect textRect = fontMetrics.boundingRect(badgeText);
-
+
// Position badge in top-right corner with some margin
const int margin = 16;
const auto headerHeight = _headerBar->isVisible() ? _headerBar->height() : 0;
@@ -885,7 +885,7 @@ void TerminalDisplay::drawBadge(QPainter &painter)
const int padding = 8;
const int badgeWidth = textRect.width() + (padding * 2);
const int badgeHeight = textRect.height() + (padding * 2);
-
+
const int badgeX = width() - badgeWidth - margin - scrollBarWidth;
const int badgeY = headerHeight + margin;
@@ -894,7 +894,7 @@ void TerminalDisplay::drawBadge(QPainter &painter)
// Draw badge background with rounded corners
QColor backgroundColor = badgeColor;
backgroundColor.setAlpha(badgeTransparency);
-
+
painter.setPen(Qt::NoPen);
painter.setBrush(backgroundColor);
painter.drawRoundedRect(badgeRect, 4, 4);
@@ -1397,8 +1397,17 @@ void TerminalDisplay::mousePressEvent(QMouseEvent *ev)
} else if (ev->button() == Qt::MiddleButton) {
processMidButtonClick(ev);
} else if (ev->button() == Qt::RightButton) {
- if (usesMouseTracking() && !_readOnly && !ev->modifiers().testFlag(Qt::ShiftModifier)) {
+ if (usesMouseTracking() && !_readOnly && !ev->modifiers().testFlag(Qt::ShiftModifier) &&
+ (_rightClickPasteMode == Enum::RightClickPasteDisabled || ev->modifiers().testFlag(Qt::ControlModifier))) {
+ // Send mouse signal to terminal if mouse tracking is enabled
sendMouseSignal(mouseButton(2, ev->modifiers()), ev->pos(), 0, true);
+ } else {
+ // Handle right-click paste
+ if (_rightClickPasteMode == Enum::RightClickPasteFromX11Selection) {
+ pasteFromX11Selection();
+ } else if (_rightClickPasteMode == Enum::RightClickPasteFromClipboard) {
+ pasteFromClipboard();
+ }
}
}
}
@@ -2538,6 +2547,11 @@ void TerminalDisplay::setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum mod
_middleClickPasteMode = mode;
}
+void TerminalDisplay::setRightClickPasteMode(Enum::RightClickPasteModeEnum mode)
+{
+ _rightClickPasteMode = mode;
+}
+
void TerminalDisplay::setCopyTextAsHTML(bool enabled)
{
_copyTextAsHTML = enabled;
@@ -3274,10 +3288,10 @@ void TerminalDisplay::setSessionController(SessionController *controller)
{
_sessionController = controller;
_headerBar->finishHeaderSetup(controller);
-
+
// Connect to session attribute changes to update badge display
if (_sessionController && !_sessionController->session().isNull()) {
- connect(_sessionController->session().data(), &Session::sessionAttributeChanged,
+ connect(_sessionController->session().data(), &Session::sessionAttributeChanged,
this, QOverload<>::of(&QWidget::update));
}
}
@@ -3334,6 +3348,7 @@ void TerminalDisplay::applyProfile(const Profile::Ptr &profile)
_clearSelection = profile->property<bool>(Profile::ClearSelectionOnCopy);
_openLinksByDirectClick = profile->property<bool>(Profile::OpenLinksByDirectClickEnabled);
setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum(profile->property<int>(Profile::MiddleClickPasteMode)));
+ setRightClickPasteMode(Enum::RightClickPasteModeEnum(profile->property<int>(Profile::RightClickPasteMode)));
setCopyTextAsHTML(profile->property<bool>(Profile::CopyTextAsHTML));
// highlight lines scrolled into view (must be applied before margin/center)
diff --git a/src/terminalDisplay/TerminalDisplay.h b/src/terminalDisplay/TerminalDisplay.h
index 75815e4c8..83c81d36f 100644
--- a/src/terminalDisplay/TerminalDisplay.h
+++ b/src/terminalDisplay/TerminalDisplay.h
@@ -669,6 +669,7 @@ private:
void setAutoCopySelectedText(bool enabled);
void setCopyTextAsHTML(bool enabled);
void setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum mode);
+ void setRightClickPasteMode(Enum::RightClickPasteModeEnum mode);
/**
* Sets the display's contents margins.
@@ -742,6 +743,7 @@ private:
bool _autoCopySelectedText = false;
bool _copyTextAsHTML = true;
Enum::MiddleClickPasteModeEnum _middleClickPasteMode = Enum::PasteFromX11Selection;
+ Enum::RightClickPasteModeEnum _rightClickPasteMode = Enum::RightClickPasteDisabled;
QString _wordCharacters;
TerminalBell _bell{Enum::NotifyBell};
diff --git a/src/widgets/EditProfileDialog.cpp b/src/widgets/EditProfileDialog.cpp
index 3d1653814..a5ef5a7fa 100644
--- a/src/widgets/EditProfileDialog.cpp
+++ b/src/widgets/EditProfileDialog.cpp
@@ -1956,6 +1956,15 @@ void EditProfileDialog::setupMousePage(const Profile::Ptr &profile)
_mouseUi->pasteFromClipboardButton->setChecked(Enum::PasteFromClipboard == middleClickPasteMode);
connect(_mouseUi->pasteFromClipboardButton, &QPushButton::clicked, this, &EditProfileDialog::pasteFromClipboard);
+ // setup right click paste mode
+ const auto rightClickPasteMode = profile->property<int>(Profile::RightClickPasteMode);
+ _mouseUi->rightClickPasteDisabledButton->setChecked(Enum::RightClickPasteDisabled == rightClickPasteMode);
+ connect(_mouseUi->rightClickPasteDisabledButton, &QPushButton::clicked, this, &EditProfileDialog::rightClickPasteDisabled);
+ _mouseUi->rightClickPasteFromClipboardButton->setChecked(Enum::RightClickPasteFromClipboard == rightClickPasteMode);
+ connect(_mouseUi->rightClickPasteFromClipboardButton, &QPushButton::clicked, this, &EditProfileDialog::rightClickPasteFromClipboard);
+ _mouseUi->rightClickPasteFromX11SelectionButton->setChecked(Enum::RightClickPasteFromX11Selection == rightClickPasteMode);
+ connect(_mouseUi->rightClickPasteFromX11SelectionButton, &QPushButton::clicked, this, &EditProfileDialog::rightClickPasteFromX11Selection);
+
_mouseUi->textEditorCustomBtn->setIcon(QIcon::fromTheme(QStringLiteral("document-edit")));
// interaction options
@@ -2284,6 +2293,21 @@ void EditProfileDialog::pasteFromClipboard()
updateTempProfileProperty(Profile::MiddleClickPasteMode, Enum::PasteFromClipboard);
}
+void EditProfileDialog::rightClickPasteDisabled()
+{
+ updateTempProfileProperty(Profile::RightClickPasteMode, Enum::RightClickPasteDisabled);
+}
+
+void EditProfileDialog::rightClickPasteFromClipboard()
+{
+ updateTempProfileProperty(Profile::RightClickPasteMode, Enum::RightClickPasteFromClipboard);
+}
+
+void EditProfileDialog::rightClickPasteFromX11Selection()
+{
+ updateTempProfileProperty(Profile::RightClickPasteMode, Enum::RightClickPasteFromX11Selection);
+}
+
void EditProfileDialog::TripleClickModeChanged(int newValue)
{
updateTempProfileProperty(Profile::TripleClickMode, newValue);
diff --git a/src/widgets/EditProfileDialog.h b/src/widgets/EditProfileDialog.h
index 97c003c7e..22f454a31 100644
--- a/src/widgets/EditProfileDialog.h
+++ b/src/widgets/EditProfileDialog.h
@@ -216,6 +216,9 @@ private Q_SLOTS:
void toggleClearSelectionOnCopy(bool);
void pasteFromX11Selection();
void pasteFromClipboard();
+ void rightClickPasteDisabled();
+ void rightClickPasteFromClipboard();
+ void rightClickPasteFromX11Selection();
void toggleAlternateScrolling(bool enable);
void toggleAllowColorFilter(bool enable);
void toggleAllowMouseTracking(bool allow);
diff --git a/src/widgets/EditProfileMousePage.ui b/src/widgets/EditProfileMousePage.ui
index 3cf184a2e..bb3081299 100644
--- a/src/widgets/EditProfileMousePage.ui
+++ b/src/widgets/EditProfileMousePage.ui
@@ -181,6 +181,71 @@
</spacer>
</item>
<item row="8" column="0">
+ <widget class="QLabel" name="rightClickPasteLabel">
+ <property name="text">
+ <string>Right-click:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QRadioButton" name="rightClickPasteDisabledButton">
+ <property name="text">
+ <string>Opens context menu</string>
+ </property>
+ <property name="toolTip">
+ <string comment="@info:tooltip">Right-click shows context menu</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">rightClickPasteFrom</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QRadioButton" name="rightClickPasteFromClipboardButton">
+ <property name="text">
+ <string>Pastes from clipboard</string>
+ </property>
+ <property name="toolTip">
+ <string comment="@info:tooltip">Control+right-click shows context menu</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">rightClickPasteFrom</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="10" column="1">
+ <widget class="QRadioButton" name="rightClickPasteFromX11SelectionButton">
+ <property name="text">
+ <string>Pastes from selection</string>
+ </property>
+ <property name="toolTip">
+ <string comment="@info:tooltip">Control+right-click shows context menu</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string notr="true">rightClickPasteFrom</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Orientation::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Policy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="12" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Copy options:</string>
@@ -190,7 +255,7 @@
</property>
</widget>
</item>
- <item row="8" column="1">
+ <item row="12" column="1">
<widget class="QCheckBox" name="copyTextToClipboardButton">
<property name="toolTip">
<string>Automatically copy selected text into clipboard</string>
@@ -200,7 +265,7 @@
</property>
</widget>
</item>
- <item row="9" column="1">
+ <item row="13" column="1">
<widget class="QCheckBox" name="copyTextAsHTMLButton">
<property name="toolTip">
<string>Copy text as HTML (including formatting, font faces, colors... etc)</string>
@@ -210,7 +275,7 @@
</property>
</widget>
</item>
- <item row="10" column="1">
+ <item row="14" column="1">
<widget class="QCheckBox" name="trimLeadingSpacesButton">
<property name="toolTip">
<string>Trim leading spaces in selected text, useful in some instances</string>
@@ -220,7 +285,7 @@
</property>
</widget>
</item>
- <item row="11" column="1">
+ <item row="15" column="1">
<widget class="QCheckBox" name="trimTrailingSpacesButton">
<property name="toolTip">
<string>Trim trailing spaces in selected text, useful in some instances</string>
@@ -230,7 +295,7 @@
</property>
</widget>
</item>
- <item row="12" column="1">
+ <item row="16" column="1">
<widget class="QCheckBox" name="clearSelectionButton">
<property name="toolTip">
<string>Clear selection after copying</string>
@@ -503,5 +568,6 @@
<buttongroups>
<buttongroup name="tripleClickMode"/>
<buttongroup name="pasteFrom"/>
+ <buttongroup name="rightClickPasteFrom"/>
</buttongroups>
</ui>
More information about the kde-doc-english
mailing list