[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