Commit ccd56f20 authored by Matan Ziv-Av's avatar Matan Ziv-Av Committed by Tomaz Canabrava
Browse files

Add click to position cursor in shell input

- Conditional on a profile option.
- Visually improve semantic integration options tab.
- Save/load semantic integration
parent 7f6d1009
......@@ -23,7 +23,6 @@
// Konsole
#include "EscapeSequenceUrlExtractor.h"
#include "keyboardtranslator/KeyboardTranslator.h"
#include "session/SessionController.h"
#include "terminalDisplay/TerminalColor.h"
#include "terminalDisplay/TerminalDisplay.h"
......@@ -2017,6 +2016,7 @@ void Vt102Emulation::reportAnswerBack()
0 = Mouse button press
1 = Mouse drag
2 = Mouse button release
3 = Mouse click to move cursor in input field
*/
void Vt102Emulation::sendMouseEvent(int cb, int cx, int cy, int eventType)
......@@ -2025,6 +2025,58 @@ void Vt102Emulation::sendMouseEvent(int cb, int cx, int cy, int eventType)
return;
}
if (eventType == 3) {
// We know we are in input mode
TerminalDisplay *currentView = _currentScreen->currentTerminalDisplay();
bool isReadOnly = false;
if (currentView != nullptr && currentView->sessionController() != nullptr) {
isReadOnly = currentView->sessionController()->isReadOnly();
}
auto point = std::make_pair(cy, cx);
if (!isReadOnly && _currentScreen->replModeStart() <= point && point <= _currentScreen->replModeEnd()) {
KeyboardTranslator::States states = KeyboardTranslator::NoState;
// get current states
if (getMode(MODE_NewLine)) {
states |= KeyboardTranslator::NewLineState;
}
if (getMode(MODE_Ansi)) {
states |= KeyboardTranslator::AnsiState;
}
if (getMode(MODE_AppCuKeys)) {
states |= KeyboardTranslator::CursorKeysState;
}
if (getMode(MODE_AppScreen)) {
states |= KeyboardTranslator::AlternateScreenState;
}
KeyboardTranslator::Entry LRKeys[2] = {_keyTranslator->findEntry(Qt::Key_Left, Qt::NoModifier, states),
_keyTranslator->findEntry(Qt::Key_Right, Qt::NoModifier, states)};
QVector<LineProperty> lineProperties = _currentScreen->getLineProperties(cy + _currentScreen->getHistLines(), cy + _currentScreen->getHistLines());
cx = qMin(cx, LineLength(lineProperties[0]));
int cuX = _currentScreen->getCursorX();
int cuY = _currentScreen->getCursorY();
QByteArray textToSend;
if (cuY != cy) {
for (int i = abs(cy - cuY); i > 0; i--) {
emulateUpDown(cy < cuY, LRKeys[cy > cuY], textToSend, i == 1 ? cx : -1);
textToSend += LRKeys[cy > cuY].text();
}
} else {
if (cuX < cx) {
for (int i = 0; i < cx - cuX; i++) {
textToSend += LRKeys[1].text();
}
} else {
for (int i = 0; i < cuX - cx; i++) {
textToSend += LRKeys[0].text();
}
}
}
Q_EMIT sendData(textToSend);
}
return;
}
// Don't send move/drag events if only press and release requested
if (eventType == 1 && getMode(MODE_Mouse1000)) {
return;
......@@ -2076,6 +2128,37 @@ void Vt102Emulation::sendMouseEvent(int cb, int cx, int cy, int eventType)
sendString(command);
}
void Vt102Emulation::emulateUpDown(bool up, KeyboardTranslator::Entry entry, QByteArray &textToSend, int toCol)
{
int cuX = _currentScreen->getCursorX();
int cuY = _currentScreen->getCursorY();
int realX = cuX;
QVector<LineProperty> lineProperties = _currentScreen->getLineProperties(cuY - 1 + _currentScreen->getHistLines(),
qMin(_currentScreen->getLines() - 1, cuY + 1) + _currentScreen->getHistLines());
int num = _currentScreen->getColumns();
if (up) {
if ((lineProperties[0] & LINE_WRAPPED) == 0) {
num = cuX + qMax(0, LineLength(lineProperties[0]) - cuX) + 1;
}
} else {
if ((lineProperties[1] & LINE_WRAPPED) == 0 || (lineProperties[2] & LINE_WRAPPED) == 0) {
realX = qMin(cuX, LineLength(lineProperties[2]) + 1);
num = LineLength(lineProperties[1]) - cuX + realX;
}
}
if (toCol > -1) {
if (toCol < realX) {
num += up ? realX - toCol : toCol - realX;
} else {
num += up ? realX - toCol : toCol - realX;
}
}
for (int i = 1; i < num; i++) {
// One more will be added by the rest of the code.
textToSend += entry.text();
}
}
/**
* The focus change event can be used by Vim (or other terminal applications)
* to recognize that the konsole window has changed focus.
......@@ -2159,26 +2242,11 @@ void Vt102Emulation::sendKeyEvent(QKeyEvent *event)
int cuY = _currentScreen->getCursorY();
if ((event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) && _currentScreen->replMode() == REPL_INPUT
&& _currentScreen->currentTerminalDisplay()->semanticUpDown()) {
if ((event->key() == Qt::Key_Up && _currentScreen->replModeStart() <= std::make_pair(cuY - 1, cuX))
|| (event->key() == Qt::Key_Down && std::make_pair(cuY + 1, cuX) <= _currentScreen->replModeEnd())) {
entry = _keyTranslator->findEntry(event->key() == Qt::Key_Up ? Qt::Key_Left : Qt::Key_Right, Qt::NoModifier, states);
QVector<LineProperty> lineProperties =
_currentScreen->getLineProperties(cuY - 1 + _currentScreen->getHistLines(),
qMin(_currentScreen->getLines() - 1, cuY + 1) + _currentScreen->getHistLines());
int num = _currentScreen->getColumns();
if (event->key() == Qt::Key_Up) {
if ((lineProperties[0] & LINE_WRAPPED) == 0) {
num = cuX + qMax(0, LineLength(lineProperties[0]) - cuX) + 1;
}
} else {
if ((lineProperties[1] & LINE_WRAPPED) == 0 || (lineProperties[2] & LINE_WRAPPED) == 0) {
num = LineLength(lineProperties[1]) - cuX + 1 + qMin(cuX - 1, LineLength(lineProperties[2]));
}
}
for (int i = 1; i < num; i++) {
// One more will be added by the rest of the code.
textToSend += entry.text();
}
bool up = event->key() == Qt::Key_Up;
if ((up && _currentScreen->replModeStart() <= std::make_pair(cuY - 1, cuX))
|| (!up && std::make_pair(cuY + 1, cuX) <= _currentScreen->replModeEnd())) {
entry = _keyTranslator->findEntry(up ? Qt::Key_Left : Qt::Key_Right, Qt::NoModifier, states);
emulateUpDown(up, entry, textToSend);
}
}
......
......@@ -17,6 +17,7 @@
// Konsole
#include "Emulation.h"
#include "Screen.h"
#include "keyboardtranslator/KeyboardTranslator.h"
class QTimer;
class QKeyEvent;
......@@ -236,6 +237,8 @@ private:
void reportColor(int c, QColor color);
void reportTerminalParms(int p);
void emulateUpDown(bool up, KeyboardTranslator::Entry entry, QByteArray &textToSend, int toCol = -1);
// clears the screen and resizes it to the specified
// number of columns
void clearScreenAndSetColumns(int columnCount);
......
......@@ -67,6 +67,9 @@ const std::vector<Profile::PropertyInfo> Profile::DefaultProperties = {
{LocalTabTitleFormat, "LocalTabTitleFormat", GENERAL_GROUP, QLatin1String("%d : %n")},
{LocalTabTitleFormat, "tabtitle", nullptr, QLatin1String("%d : %n")},
{RemoteTabTitleFormat, "RemoteTabTitleFormat", GENERAL_GROUP, QLatin1String("(%u) %H")},
{SemanticHints, "SemanticHints", GENERAL_GROUP, 1},
{SemanticUpDown, "SemanticUpDown", GENERAL_GROUP, false},
{SemanticInputClick, "SemanticInputClick", GENERAL_GROUP, false},
{ShowTerminalSizeHint, "ShowTerminalSizeHint", GENERAL_GROUP, true},
{StartInCurrentSessionDir, "StartInCurrentSessionDir", GENERAL_GROUP, true},
{SilenceSeconds, "SilenceSeconds", GENERAL_GROUP, 10},
......
......@@ -359,6 +359,9 @@ public:
* key presses that emulate the same cursor movement
*/
SemanticUpDown,
/** (bool) If true, move cursor with Left/Right keys when mouse clicks in input area
*/
SemanticInputClick,
};
Q_ENUM(Property)
......@@ -759,6 +762,11 @@ public:
return property<bool>(Profile::SemanticUpDown);
}
bool semanticInputClick() const
{
return property<bool>(Profile::SemanticInputClick);
}
/** Return a list of all properties names and their type
* (for use with -p option).
*/
......
......@@ -1157,6 +1157,10 @@ void TerminalDisplay::mousePressEvent(QMouseEvent *ev)
Q_EMIT mouseSignal(0, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), 0);
}
}
if (_semanticInputClick && (ev->modifiers() & Qt::ControlModifier) == 0 && _screenWindow->screen()->replMode() == REPL_INPUT) {
Q_EMIT mouseSignal(0, charColumn, charLine + _scrollBar->value() - _scrollBar->maximum(), 3);
}
} else if (ev->button() == Qt::MiddleButton) {
processMidButtonClick(ev);
} else if (ev->button() == Qt::RightButton) {
......@@ -2830,6 +2834,7 @@ void TerminalDisplay::applyProfile(const Profile::Ptr &profile)
_bidiEnabled = profile->bidiRenderingEnabled();
_semanticUpDown = profile->semanticUpDown();
_semanticHints = profile->semanticHints();
_semanticInputClick = profile->semanticInputClick();
_trimLeadingSpaces = profile->property<bool>(Profile::TrimLeadingSpacesInSelectedText);
_trimTrailingSpaces = profile->property<bool>(Profile::TrimTrailingSpacesInSelectedText);
_openLinksByDirectClick = profile->property<bool>(Profile::OpenLinksByDirectClickEnabled);
......
......@@ -776,6 +776,7 @@ private:
int _semanticHints;
bool _semanticUpDown;
bool _semanticInputClick;
};
}
......
......@@ -474,6 +474,8 @@ void EditProfileDialog::setupGeneralPage(const Profile::Ptr &profile)
} else {
_generalUi->setAsDefaultButton->setText(i18n("Default profile"));
}
_generalUi->semanticUpDown->setChecked(profile->semanticUpDown());
_generalUi->semanticInputClick->setChecked(profile->semanticInputClick());
// signals and slots
connect(_generalUi->dirSelectButton, &QToolButton::clicked, this, &Konsole::EditProfileDialog::selectInitialDir);
......@@ -484,6 +486,7 @@ void EditProfileDialog::setupGeneralPage(const Profile::Ptr &profile)
connect(_generalUi->commandEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::commandChanged);
connect(_generalUi->environmentEditButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::showEnvironmentEditor);
connect(_generalUi->semanticUpDown, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::semanticUpDown);
connect(_generalUi->semanticInputClick, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::semanticInputClick);
connect(_generalUi->terminalColumnsEntry, QOverload<int>::of(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalColumnsEntryChanged);
connect(_generalUi->terminalRowsEntry, QOverload<int>::of(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalRowsEntryChanged);
......@@ -504,7 +507,6 @@ void EditProfileDialog::setupGeneralPage(const Profile::Ptr &profile)
{_generalUi->semanticHintsAlways, Enum::SemanticHintsAlways},
},
};
setupButtonGroup(semanticHints, profile);
}
......@@ -636,6 +638,11 @@ void EditProfileDialog::semanticUpDown(bool enable)
updateTempProfileProperty(Profile::SemanticUpDown, enable);
}
void EditProfileDialog::semanticInputClick(bool enable)
{
updateTempProfileProperty(Profile::SemanticInputClick, enable);
}
void EditProfileDialog::initialDirChanged(const QString &dir)
{
updateTempProfileProperty(Profile::Directory, dir);
......
......@@ -121,6 +121,7 @@ private Q_SLOTS:
void startInSameDir(bool);
void commandChanged(const QString &command);
void semanticUpDown(bool);
void semanticInputClick(bool enable);
// tab page
void tabTitleFormatChanged(const QString &format);
......
......@@ -32,7 +32,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="general">
<attribute name="title">
......@@ -374,6 +374,13 @@
<string>Semantic Integration</string>
</attribute>
<layout class="QGridLayout">
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="semanticUpDown">
<property name="text">
<string>Up/Down Arrows emulation</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="semanticHintsURL">
<property name="text">
......@@ -384,6 +391,26 @@
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="semanticHintsNever">
<property name="text">
<string comment="Never">Never</string>
</property>
<attribute name="buttonGroup">
<string notr="true">semanticHints</string>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="semanticHintsAlways">
<property name="text">
<string comment="Always">Always</string>
</property>
<attribute name="buttonGroup">
<string notr="true">semanticHints</string>
</attribute>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
......@@ -400,33 +427,14 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="semanticHintsNever">
<item row="5" column="0">
<widget class="QCheckBox" name="semanticInputClick">
<property name="text">
<string comment="Never">Never</string>
<string>Mouse click in input line moves cursor</string>
</property>
<attribute name="buttonGroup">
<string notr="true">semanticHints</string>
</attribute>
</widget>
</item>
<item row="4" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -439,23 +447,6 @@
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="semanticHintsAlways">
<property name="text">
<string comment="Always">Always</string>
</property>
<attribute name="buttonGroup">
<string notr="true">semanticHints</string>
</attribute>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="semanticUpDown">
<property name="text">
<string>Up/Down Arrows emulation</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
......
Supports Markdown
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