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>
