[utilities/konsole] /: Add keyboard selection mode

Tomaz Canabrava null at kde.org
Mon Oct 3 12:02:51 BST 2022


Git commit f26f71db013a5440560fd3be3fa4cf249f1fb8dd by Tomaz  Canabrava, on behalf of Matan Ziv-Av.
Committed on 03/10/2022 at 10:46.
Pushed by tcanabrava into branch 'master'.

Add keyboard selection mode

Similar to screen copy/scrollback mode it allows browsing the scrollback
and selecting text.

Selection is done either by standard GUI shift+arrows, or `vi` style with
`v` starting/ending selection.

BUG: 100317

M  +25   -2    doc/manual/index.docbook
M  +117  -0    src/Screen.cpp
M  +16   -1    src/Screen.h
M  +5    -4    src/SearchHistoryTask.cpp
M  +10   -4    src/Vt102Emulation.cpp
M  +11   -0    src/session/Session.cpp
M  +5    -0    src/session/Session.h
M  +20   -2    src/session/SessionController.cpp
M  +1    -0    src/session/SessionController.h
M  +175  -0    src/terminalDisplay/TerminalDisplay.cpp
M  +14   -0    src/terminalDisplay/TerminalDisplay.h

https://invent.kde.org/utilities/konsole/commit/f26f71db013a5440560fd3be3fa4cf249f1fb8dd

diff --git a/doc/manual/index.docbook b/doc/manual/index.docbook
index 93dd9a922..7f29d1083 100644
--- a/doc/manual/index.docbook
+++ b/doc/manual/index.docbook
@@ -52,8 +52,8 @@
 
 <legalnotice>&FDLNotice;</legalnotice>
 
-<date>2021-10-28</date>
-<releaseinfo>Applications 21.12</releaseinfo>
+<date>2022-09-16</date>
+<releaseinfo>Applications 22.12</releaseinfo>
 
 <abstract><para>&konsole; is &kde;'s terminal emulator.</para></abstract>
 
@@ -110,6 +110,29 @@ to open this window).
 
 </sect1>
 
+<sect1 id="selection">
+<title>Selection Mode</title>
+<para>&konsole; has a selction by keyboard mode. In this mode it is possible to move around the scrollback and select text
+without the mouse.</para>
+
+<para>
+Enter and leave this mode by using the keyboard shortcut (<keycombo action="simul">&Ctrl;&Shift;<keycap>D</keycap></keycombo> by default).
+</para>
+
+<para>
+Moving the cursor: Arrows, <keycap>PageUp</keycap>, <keycap>PageDown</keycap>, <keycap>Home</keycap>, <keycap>End</keycap>.
+</para>
+
+<para>Moving the cursor <application>vi</application> style: h,j,k,l, to move one character, <keycap>Ctrl</keycap>+b,f,u,d for page up/down or half page up/down.</para>
+
+<para>
+Select text by using <keycap>Ctrl</keycap> or <keycap>Shift</keycap> with arrows, or by using <keycap>V</keycap> to start selection, moving the cursor and then <keycap>V</keycap> again to end selection.
+<keycombo>&Shift;<keycap>V</keycap></keycombo> selects whole lines, instead of characters.
+</para>
+
+</sect1>
+
+
 <sect1 id="profiles">
 <title>Profiles</title>
 <para>Profiles allow the user to quickly and easily automate the running
diff --git a/src/Screen.cpp b/src/Screen.cpp
index 6c5bc7e6d..f537f14ae 100644
--- a/src/Screen.cpp
+++ b/src/Screen.cpp
@@ -176,6 +176,117 @@ void Screen::cursorRight(int n)
     _cuX = qMin(getScreenLineColumns(_cuY) - 1, _cuX + n);
 }
 
+void Screen::initSelCursor()
+{
+    _selCuX = _cuX;
+    _selCuY = _cuY;
+}
+
+int Screen::selCursorUp(int n)
+{
+    if (n == 0) {
+        // Half page
+        n = _lines / 2;
+    } else if (n == -1) {
+        // Full page
+        n = _lines;
+    } else if (n == -2) {
+        // First line
+        n = _selCuY + _history->getLines();
+    }
+    _selCuY = qMax(-_history->getLines(), _selCuY - n);
+    return _selCuY;
+}
+
+int Screen::selCursorDown(int n)
+{
+    if (n == 0) {
+        // Half page
+        n = _lines / 2;
+    } else if (n == -1) {
+        // Full page
+        n = _lines;
+    } else if (n == -2) {
+        // Last line
+        n = _lines - 1 - _selCuY;
+    }
+    _selCuY = qMin(_lines - 1, _selCuY + n);
+    return _selCuY;
+}
+
+int Screen::selCursorLeft(int n)
+{
+    if (n == 0) {
+        // Home
+        n = _selCuX;
+    }
+    if (_selCuX >= n) {
+        _selCuX -= n;
+    } else {
+        if (_selCuY > -_history->getLines()) {
+            _selCuY -= 1;
+            _selCuX = qMax(_columns - n + _selCuX, 0);
+        } else {
+            _selCuX = 0;
+        }
+    }
+    return _selCuY;
+}
+
+int Screen::selCursorRight(int n)
+{
+    if (n == 0) {
+        // End
+        n = _columns - _selCuX - 1;
+    }
+    if (_selCuX + n < _columns) {
+        _selCuX += n;
+    } else {
+        if (_selCuY < _lines - 1) {
+            _selCuY += 1;
+            _selCuX = qMin(n + _selCuX - _columns, _columns - 1);
+        } else {
+            _selCuX = _columns - 1;
+        }
+    }
+    return _selCuY;
+}
+
+int Screen::selSetSelectionStart(int mode)
+{
+    // mode: 0 = character selection
+    //       1 = line selection
+    int x = _selCuX;
+    if (mode == 1) {
+        x = 0;
+    }
+    setSelectionStart(x, _selCuY + _history->getLines(), false);
+    return 0;
+}
+
+int Screen::selSetSelectionEnd(int mode)
+{
+    int y = _selCuY + _history->getLines();
+    int x = _selCuX;
+    if (mode == 1) {
+        int l = _selBegin / _columns;
+        if (y < l) {
+            if (_selBegin % _columns == 0) {
+                setSelectionStart(_columns - 1, l, false);
+            }
+            x = 0;
+        } else {
+            x = _columns - 1;
+            if (_selBegin % _columns != 0) {
+                setSelectionStart(0, l, false);
+            }
+        }
+    }
+    setSelectionEnd(x, y, false);
+    Q_EMIT _currentTerminalDisplay->screenWindow()->selectionChanged();
+    return 0;
+}
+
 void Screen::setMargins(int top, int bot)
 //=STBM
 {
@@ -767,6 +878,11 @@ void Screen::getImage(Character *dest, int size, int startLine, int endLine) con
     if (getMode(MODE_Cursor) && cursorIndex < _columns * mergedLines) {
         dest[cursorIndex].rendition.f.cursor = 1;
     }
+    cursorIndex = loc(_selCuX, _selCuY - startLine + _history->getLines());
+
+    if (getMode(MODE_SelectCursor) && cursorIndex >= 0 && cursorIndex < _columns * mergedLines) {
+        dest[cursorIndex].rendition.f.cursor = 1;
+    }
 }
 
 QVector<LineProperty> Screen::getLineProperties(int startLine, int endLine) const
@@ -841,6 +957,7 @@ void Screen::reset(bool softReset, bool preservePrompt)
     saveMode(MODE_Insert); // overstroke
 
     setMode(MODE_Cursor); // cursor visible
+    resetMode(MODE_SelectCursor);
 
     _topMargin = 0;
     _bottomMargin = _lines - 1;
diff --git a/src/Screen.h b/src/Screen.h
index b0587e51d..b5d0c3197 100644
--- a/src/Screen.h
+++ b/src/Screen.h
@@ -29,7 +29,8 @@
 #define MODE_Cursor 4
 #define MODE_NewLine 5
 #define MODE_AppScreen 6
-#define MODES_SCREEN 7
+#define MODE_SelectCursor 7
+#define MODES_SCREEN 8
 
 #define REPL_None 0
 #define REPL_PROMPT 1
@@ -148,6 +149,16 @@ public:
     void setCursorX(int x);
     /** Position the cursor at line @p y, column @p x. */
     void setCursorYX(int y, int x);
+
+    void initSelCursor();
+    int selCursorUp(int n);
+    int selCursorDown(int n);
+    int selCursorLeft(int n);
+    int selCursorRight(int n);
+
+    int selSetSelectionStart(int mode);
+    int selSetSelectionEnd(int mode);
+
     /**
      * Sets the margins for scrolling the screen.
      *
@@ -805,6 +816,10 @@ private:
     int _cuX;
     int _cuY;
 
+    // select mode cursor location
+    int _selCuX;
+    int _selCuY;
+
     // cursor color and rendition info
     CharacterColor _currentForeground;
     CharacterColor _currentBackground;
diff --git a/src/SearchHistoryTask.cpp b/src/SearchHistoryTask.cpp
index 4997843b8..0a1667361 100644
--- a/src/SearchHistoryTask.cpp
+++ b/src/SearchHistoryTask.cpp
@@ -148,10 +148,11 @@ void SearchHistoryTask::executeOnScreenWindow(const QPointer<Session> &session,
             string.clear();
             line = endLine;
         } while (startLine != endLine);
-
-        // if no match was found, clear selection to indicate this
-        window->clearSelection();
-        window->notifyOutputChanged();
+        if (!session->getSelectMode()) {
+            // if no match was found, clear selection to indicate this,
+            window->clearSelection();
+            window->notifyOutputChanged();
+        }
     }
 
     Q_EMIT completed(false);
diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp
index b50a11e51..bcbac76b1 100644
--- a/src/Vt102Emulation.cpp
+++ b/src/Vt102Emulation.cpp
@@ -2040,8 +2040,11 @@ void Vt102Emulation::sendMouseEvent(int cb, int cx, int cy, int eventType)
         // We know we are in input mode
         TerminalDisplay *currentView = _currentScreen->currentTerminalDisplay();
         bool isReadOnly = false;
-        if (currentView != nullptr && currentView->sessionController() != nullptr) {
-            isReadOnly = currentView->sessionController()->isReadOnly();
+        // if (currentView != nullptr && currentView->sessionController() != nullptr) {
+        //     isReadOnly = currentView->sessionController()->isReadOnly();
+        // }
+        if (currentView != nullptr) {
+            isReadOnly = currentView->getReadOnly();
         }
         auto point = std::make_pair(cy, cx);
         if (!isReadOnly && _currentScreen->replModeStart() <= point && point <= _currentScreen->replModeEnd()) {
@@ -2196,8 +2199,11 @@ void Vt102Emulation::sendKeyEvent(QKeyEvent *event)
 
     TerminalDisplay *currentView = _currentScreen->currentTerminalDisplay();
     bool isReadOnly = false;
-    if (currentView != nullptr && currentView->sessionController() != nullptr) {
-        isReadOnly = currentView->sessionController()->isReadOnly();
+    // if (currentView != nullptr && currentView->sessionController() != nullptr) {
+    //     isReadOnly = currentView->sessionController()->isReadOnly();
+    // }
+    if (currentView != nullptr) {
+        isReadOnly = currentView->getReadOnly();
     }
 
     // get current states
diff --git a/src/session/Session.cpp b/src/session/Session.cpp
index f3b8c94ce..19c7ed151 100644
--- a/src/session/Session.cpp
+++ b/src/session/Session.cpp
@@ -1857,6 +1857,17 @@ void Session::setReadOnly(bool readOnly)
         Q_EMIT readOnlyChanged();
     }
 }
+bool Session::getSelectMode() const
+{
+    return _selectMode;
+}
+
+void Session::setSelectMode(bool mode)
+{
+    if (_selectMode != mode) {
+        _selectMode = mode;
+    }
+}
 
 void Session::setColor(const QColor &color)
 {
diff --git a/src/session/Session.h b/src/session/Session.h
index 7291602d7..6da867001 100644
--- a/src/session/Session.h
+++ b/src/session/Session.h
@@ -406,6 +406,9 @@ public:
     bool isReadOnly() const;
     void setReadOnly(bool readOnly);
 
+    bool getSelectMode() const;
+    void setSelectMode(bool mode);
+
     // Returns true if the current screen is the secondary/alternate one
     // or false if it's the primary/normal buffer
     bool isPrimaryScreen();
@@ -875,6 +878,8 @@ private:
     bool _isPrimaryScreen = true;
 
     QString _currentHostName;
+
+    bool _selectMode = false;
 };
 
 }
diff --git a/src/session/SessionController.cpp b/src/session/SessionController.cpp
index 8bd91857c..84ab8d7af 100644
--- a/src/session/SessionController.cpp
+++ b/src/session/SessionController.cpp
@@ -452,12 +452,14 @@ void SessionController::setupPrimaryScreenSpecificActions(bool use)
     QAction *clearAction = collection->action(QStringLiteral("clear-history"));
     QAction *resetAction = collection->action(QStringLiteral("clear-history-and-reset"));
     QAction *selectAllAction = collection->action(QStringLiteral("select-all"));
+    QAction *selectModeAction = collection->action(QStringLiteral("select-mode"));
     QAction *selectLineAction = collection->action(QStringLiteral("select-line"));
 
     // these actions are meaningful only when primary screen is used.
     clearAction->setEnabled(use);
     resetAction->setEnabled(use);
     selectAllAction->setEnabled(use);
+    selectModeAction->setEnabled(use);
     selectLineAction->setEnabled(use);
 }
 
@@ -716,6 +718,11 @@ void SessionController::setupCommonActions()
     action->setText(i18n("&Select All"));
     action->setIcon(QIcon::fromTheme(QStringLiteral("edit-select-all")));
 
+    action = collection->addAction(QStringLiteral("select-mode"), this, &SessionController::selectMode);
+    action->setText(i18n("Select &Mode"));
+    action->setIcon(QIcon::fromTheme(QStringLiteral("edit-select")));
+    collection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D));
+
     action = collection->addAction(QStringLiteral("select-line"), this, &SessionController::selectLine);
     action->setText(i18n("Select &Line"));
 
@@ -1208,6 +1215,17 @@ void SessionController::selectAll()
 {
     view()->selectAll();
 }
+void SessionController::selectMode()
+{
+    if (!session().isNull()) {
+        QAction *readonlyAction = actionCollection()->action(QStringLiteral("view-readonly"));
+        bool Mode = session()->getSelectMode();
+        session()->setSelectMode(!Mode);
+        readonlyAction->setEnabled(Mode);
+        view()->setSelectMode(!Mode);
+    }
+}
+
 void SessionController::selectLine()
 {
     view()->selectCurrentLine();
@@ -1563,7 +1581,7 @@ void SessionController::searchTextChanged(const QString &text)
     _searchText = text;
 
     if (text.isEmpty()) {
-        view()->screenWindow()->clearSelection();
+        view()->clearMouseSelection();
         view()->screenWindow()->scrollTo(_searchStartLine);
     }
 
@@ -1673,7 +1691,7 @@ void SessionController::changeSearchMatch()
     Q_ASSERT(_searchFilter);
 
     // reset Selection for new case match
-    view()->screenWindow()->clearSelection();
+    view()->clearMouseSelection();
     beginSearch(_searchBar->searchText(), reverseSearchChecked() ? Enum::BackwardsSearch : Enum::ForwardsSearch);
 }
 void SessionController::showHistoryOptions()
diff --git a/src/session/SessionController.h b/src/session/SessionController.h
index 39eb56370..d01c7acd5 100644
--- a/src/session/SessionController.h
+++ b/src/session/SessionController.h
@@ -228,6 +228,7 @@ private Q_SLOTS:
     void copyInputOutput();
     void paste();
     void selectAll();
+    void selectMode();
     void selectLine();
     void pasteFromX11Selection(); // shortcut only
     void copyInputActionsTriggered(QAction *action);
diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp
index 9d5e4eafe..3ef00bdb6 100644
--- a/src/terminalDisplay/TerminalDisplay.cpp
+++ b/src/terminalDisplay/TerminalDisplay.cpp
@@ -2492,6 +2492,23 @@ KMessageWidget *TerminalDisplay::createMessageWidget(const QString &text)
     return widget;
 }
 
+void TerminalDisplay::setSelectMode(bool mode)
+{
+    _readOnly = mode;
+    Screen *screen = screenWindow()->screen();
+    if (mode) {
+        screen->initSelCursor();
+        screen->clearSelection();
+        screen->setMode(MODE_SelectCursor);
+        _actSel = 0;
+        _selModeModifiers = 0;
+        _selModeByModifiers = false;
+    } else {
+        screen->resetMode(MODE_SelectCursor);
+    }
+    screenWindow()->notifyOutputChanged();
+}
+
 void TerminalDisplay::updateReadOnlyState(bool readonly)
 {
     if (_readOnly == readonly) {
@@ -2513,8 +2530,159 @@ void TerminalDisplay::updateReadOnlyState(bool readonly)
     _readOnly = readonly;
 }
 
+#define SELECT_BY_MODIFIERS                                                                                                                                    \
+    if (startSelect) {                                                                                                                                         \
+        _screenWindow->clearSelection();                                                                                                                       \
+        _actSel = 2;                                                                                                                                           \
+        screen->selSetSelectionStart(false);                                                                                                                   \
+        _selModeByModifiers = true;                                                                                                                            \
+    }
+
 void TerminalDisplay::keyPressEvent(QKeyEvent *event)
 {
+    Screen *screen = screenWindow()->screen();
+    int histLines = screen->getHistLines();
+    bool moved = true;
+    if (session()->getSelectMode()) {
+        int y;
+        bool startSelect = false;
+        int modifiers = event->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
+        if (_selModeModifiers != modifiers) {
+            if (modifiers == 0) {
+                if (_selModeByModifiers) {
+                    _actSel = 0;
+                    _selModeModifiers = 0;
+                    _selModeByModifiers = false;
+                }
+            } else {
+                if (event->key() >= Qt::Key_Home && event->key() <= Qt::Key_PageDown) {
+                    startSelect = true;
+                    _selModeModifiers = modifiers;
+                }
+            }
+        }
+        switch (event->key()) {
+        case Qt::Key_Left:
+        case Qt::Key_H:
+            SELECT_BY_MODIFIERS;
+            y = screen->selCursorLeft(1);
+            if (histLines + y < screenWindow()->currentLine()) {
+                scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine());
+            }
+            break;
+        case Qt::Key_Up:
+        case Qt::Key_K:
+            SELECT_BY_MODIFIERS;
+            y = screen->selCursorUp(1);
+            if (histLines + y < screenWindow()->currentLine()) {
+                scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine());
+            }
+            break;
+        case Qt::Key_Right:
+        case Qt::Key_L:
+            SELECT_BY_MODIFIERS;
+            y = screen->selCursorRight(1);
+            if (histLines + y >= screenWindow()->currentLine() + screen->getLines()) {
+                scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine() - screen->getLines() + 1);
+            }
+            break;
+        case Qt::Key_Down:
+        case Qt::Key_J:
+            SELECT_BY_MODIFIERS;
+            y = screen->selCursorDown(1);
+            if (histLines + y >= screenWindow()->currentLine() + screen->getLines()) {
+                scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine() - screen->getLines() + 1);
+            }
+            break;
+        case Qt::Key_Home:
+            SELECT_BY_MODIFIERS;
+            screen->selCursorLeft(0);
+            break;
+        case Qt::Key_End:
+            SELECT_BY_MODIFIERS;
+            screen->selCursorRight(0);
+            break;
+        case Qt::Key_V:
+            if (_actSel == 0 || _selModeByModifiers) {
+                _screenWindow->clearSelection();
+                _actSel = 2;
+                _lineSelectionMode = event->text() == QStringLiteral("V");
+                screen->selSetSelectionStart(_lineSelectionMode);
+                _selModeByModifiers = 0;
+            } else {
+                _actSel = 0;
+            }
+            break;
+        case Qt::Key_PageUp:
+            SELECT_BY_MODIFIERS;
+            y = screen->selCursorUp(-_scrollBar->scrollFullPage());
+            if (histLines + y < screenWindow()->currentLine()) {
+                scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine());
+            }
+            break;
+        case Qt::Key_PageDown:
+            SELECT_BY_MODIFIERS;
+            y = screen->selCursorDown(-_scrollBar->scrollFullPage());
+            if (histLines + y >= screenWindow()->currentLine() + screen->getLines()) {
+                scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine() - screen->getLines() + 1);
+            }
+            break;
+        case Qt::Key_F:
+        case Qt::Key_D:
+            if (event->modifiers() & Qt::ControlModifier) {
+                y = screen->selCursorDown(-(event->key() == Qt::Key_F));
+                if (histLines + y >= screenWindow()->currentLine() + screen->getLines()) {
+                    scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine() - screen->getLines() + 1);
+                }
+            } else {
+                moved = false;
+            }
+            break;
+        case Qt::Key_B:
+        case Qt::Key_U:
+            if (event->modifiers() & Qt::ControlModifier) {
+                y = screen->selCursorUp(-(event->key() == Qt::Key_B));
+                if (histLines + y < screenWindow()->currentLine()) {
+                    scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine());
+                }
+            } else {
+                moved = false;
+            }
+            break;
+        case Qt::Key_G:
+            if (event->text() == QStringLiteral("G")) {
+                y = screen->selCursorDown(-2);
+                screen->selCursorRight(0);
+                if (histLines + y >= screenWindow()->currentLine() + screen->getLines()) {
+                    scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine() - screen->getLines() + 1);
+                }
+            } else {
+                y = screen->selCursorUp(-2);
+                screen->selCursorLeft(0);
+                if (histLines + y < screenWindow()->currentLine()) {
+                    scrollScreenWindow(ScreenWindow::RelativeScrollMode::ScrollLines, histLines + y - screenWindow()->currentLine());
+                }
+            }
+            break;
+        default:
+            moved = false;
+            break;
+        }
+        if (event->text() == QStringLiteral("^")) {
+            // Might be on different key(), depending on keyboard layout
+            screen->selCursorLeft(0);
+            moved = true;
+        } else if (event->text() == QStringLiteral("$")) {
+            // Might be on different key(), depending on keyboard layout
+            screen->selCursorRight(0);
+            moved = true;
+        }
+        if (moved && _actSel > 0) {
+            screen->selSetSelectionEnd(_lineSelectionMode);
+        }
+        screenWindow()->notifyOutputChanged();
+        return;
+    }
     {
         auto [charLine, charColumn] = getCharacterPosition(mapFromGlobal(QCursor::pos()), !usesMouseTracking());
 
@@ -2935,6 +3103,13 @@ int TerminalDisplay::selectionState() const
     return _actSel;
 }
 
+void TerminalDisplay::clearMouseSelection()
+{
+    if (!session()->getSelectMode()) {
+        screenWindow()->clearSelection();
+    }
+}
+
 int TerminalDisplay::bidiMap(Character *screenline,
                              QString &line,
                              int *log2line,
diff --git a/src/terminalDisplay/TerminalDisplay.h b/src/terminalDisplay/TerminalDisplay.h
index 7ac2cd524..649ac7895 100644
--- a/src/terminalDisplay/TerminalDisplay.h
+++ b/src/terminalDisplay/TerminalDisplay.h
@@ -395,6 +395,13 @@ public:
     // Used to show/hide the message widget
     void updateReadOnlyState(bool readonly);
 
+    void setSelectMode(bool readonly);
+
+    bool getReadOnly() const
+    {
+        return _readOnly;
+    }
+
     // Get mapping between visual and logical positions in line
     // returns the index of the last non space character.
     int bidiMap(Character *screenline,
@@ -409,6 +416,10 @@ public:
 
     void showNotification(QString text);
 
+    //
+    // Clear mouse selection, but not keyboard selection
+    void clearMouseSelection();
+
 public Q_SLOTS:
     /**
      * Causes the terminal display to fetch the latest character image from the associated
@@ -791,6 +802,9 @@ private:
     bool _semanticInputClick;
 
     UBiDi *ubidi = nullptr;
+
+    int _selModeModifiers;
+    bool _selModeByModifiers; // Selection started by Shift+Arrow
 };
 
 }



More information about the kde-doc-english mailing list