forked from qt-creator/qt-creator
Terminal: Show key when input is hidden
Change-Id: I5fca6a8c4f43ea2b95bad4df247b5df0abad521c Reviewed-by: Alessandro Portale <alessandro.portale@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
7
src/libs/3rdparty/libptyqt/iptyprocess.h
vendored
7
src/libs/3rdparty/libptyqt/iptyprocess.h
vendored
@@ -11,6 +11,8 @@ class IPtyProcess
|
||||
{
|
||||
public:
|
||||
enum PtyType { UnixPty = 0, WinPty = 1, ConPty = 2, AutoPty = 3 };
|
||||
enum PtyInputFlag { None = 0x0, InputModeHidden = 0x1, };
|
||||
Q_DECLARE_FLAGS(PtyInputFlags, PtyInputFlag)
|
||||
|
||||
IPtyProcess() = default;
|
||||
IPtyProcess(const IPtyProcess &) = delete;
|
||||
@@ -43,6 +45,8 @@ public:
|
||||
return m_trace;
|
||||
}
|
||||
|
||||
PtyInputFlags inputFlags() { return m_inputFlags; }
|
||||
|
||||
protected:
|
||||
QString m_shellPath;
|
||||
QString m_lastError;
|
||||
@@ -50,6 +54,9 @@ protected:
|
||||
int m_exitCode{0};
|
||||
QPair<qint16, qint16> m_size; //cols / rows
|
||||
bool m_trace{false};
|
||||
PtyInputFlags m_inputFlags;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(IPtyProcess::PtyInputFlags)
|
||||
|
||||
#endif // IPTYPROCESS_H
|
||||
|
||||
@@ -172,6 +172,12 @@ bool UnixPtyProcess::startProcess(const QString &shellPath,
|
||||
static std::array<char, maxRead> buffer;
|
||||
|
||||
int len = ::read(m_shellProcess.m_handleMaster, buffer.data(), buffer.size());
|
||||
|
||||
struct termios termAttributes;
|
||||
tcgetattr(m_shellProcess.m_handleMaster, &termAttributes);
|
||||
const bool isPasswordEntry = !(termAttributes.c_lflag & ECHO) && (termAttributes.c_lflag & ICANON);
|
||||
m_inputFlags.setFlag(PtyInputFlag::InputModeHidden, isPasswordEntry);
|
||||
|
||||
if (len > 0) {
|
||||
m_shellReadBuffer.append(buffer.data(), len);
|
||||
m_shellProcess.emitReadyRead();
|
||||
|
||||
@@ -7,6 +7,7 @@ add_qtc_library(TerminalLib
|
||||
scrollback.cpp scrollback.h
|
||||
surfaceintegration.h
|
||||
terminal_global.h
|
||||
terminal.qrc
|
||||
terminalsurface.cpp terminalsurface.h
|
||||
terminalview.cpp terminalview.h
|
||||
)
|
||||
|
||||
BIN
src/libs/solutions/terminal/images/passwordlock.png
Normal file
BIN
src/libs/solutions/terminal/images/passwordlock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 840 B |
5
src/libs/solutions/terminal/terminal.qrc
Normal file
5
src/libs/solutions/terminal/terminal.qrc
Normal file
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/terminal">
|
||||
<file>images/passwordlock.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
bool m_cursorBlinkState{true};
|
||||
bool m_allowBlinkingCursor{true};
|
||||
bool m_allowMouseTracking{true};
|
||||
bool m_passwordModeActive{false};
|
||||
|
||||
SurfaceIntegration *m_surfaceIntegration{nullptr};
|
||||
};
|
||||
@@ -258,6 +259,14 @@ void TerminalView::setColors(const std::array<QColor, 20> &newColors)
|
||||
update();
|
||||
}
|
||||
|
||||
void TerminalView::setPasswordMode(bool passwordMode)
|
||||
{
|
||||
if (passwordMode != d->m_passwordModeActive) {
|
||||
d->m_passwordModeActive = passwordMode;
|
||||
updateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalView::setFont(const QFont &font)
|
||||
{
|
||||
QAbstractScrollArea::setFont(font);
|
||||
@@ -731,16 +740,37 @@ void TerminalView::paintCursor(QPainter &p) const
|
||||
{
|
||||
auto cursor = d->m_surface->cursor();
|
||||
|
||||
if (!d->m_preEditString.isEmpty())
|
||||
cursor.shape = Cursor::Shape::Underline;
|
||||
const int cursorCellWidth = d->m_surface->cellWidthAt(cursor.position.x(), cursor.position.y());
|
||||
|
||||
if (!d->m_preEditString.isEmpty()) {
|
||||
cursor.shape = Cursor::Shape::Underline;
|
||||
} else if (d->m_passwordModeActive) {
|
||||
QRectF cursorRect = QRectF(gridToGlobal(cursor.position),
|
||||
gridToGlobal({cursor.position.x() + cursorCellWidth,
|
||||
cursor.position.y()},
|
||||
true))
|
||||
.toAlignedRect();
|
||||
|
||||
const qreal dpr = p.device()->devicePixelRatioF();
|
||||
const QString key = QString("terminalpasswordlock-")
|
||||
% QString::number(cursorRect.size().height())
|
||||
% "@" % QString::number(dpr);
|
||||
QPixmap px;
|
||||
if (!QPixmapCache::find(key, &px)) {
|
||||
const QPixmap lock(":/terminal/images/passwordlock.png");
|
||||
px = lock.scaledToHeight(cursorRect.size().height() * dpr, Qt::SmoothTransformation);
|
||||
px.setDevicePixelRatio(dpr);
|
||||
QPixmapCache::insert(key, px);
|
||||
}
|
||||
|
||||
p.drawPixmap(cursorRect.topLeft(), px);
|
||||
|
||||
return;
|
||||
}
|
||||
const bool blinkState = !cursor.blink || d->m_cursorBlinkState || !d->m_allowBlinkingCursor
|
||||
|| !d->m_cursorBlinkTimer.isActive();
|
||||
|
||||
if (cursor.visible && blinkState) {
|
||||
const int cursorCellWidth = d->m_surface->cellWidthAt(cursor.position.x(),
|
||||
cursor.position.y());
|
||||
|
||||
QRectF cursorRect = QRectF(gridToGlobal(cursor.position),
|
||||
gridToGlobal({cursor.position.x() + cursorCellWidth,
|
||||
cursor.position.y()},
|
||||
@@ -984,6 +1014,9 @@ void TerminalView::updateViewport()
|
||||
|
||||
void TerminalView::updateViewportRect(const QRect &rect)
|
||||
{
|
||||
if (d->m_passwordModeActive)
|
||||
viewport()->update();
|
||||
else
|
||||
viewport()->update(rect);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@ public:
|
||||
void setSurfaceIntegration(SurfaceIntegration *surfaceIntegration);
|
||||
void setColors(const std::array<QColor, 20> &colors);
|
||||
|
||||
void setPasswordMode(bool passwordMode);
|
||||
|
||||
struct Link
|
||||
{
|
||||
QString text;
|
||||
|
||||
@@ -410,6 +410,13 @@ public:
|
||||
}
|
||||
|
||||
connect(m_ptyProcess->notifier(), &QIODevice::readyRead, this, [this] {
|
||||
if (m_setup.m_ptyData->ptyInputFlagsChangedHandler()
|
||||
&& m_inputFlags != m_ptyProcess->inputFlags()) {
|
||||
m_inputFlags = m_ptyProcess->inputFlags();
|
||||
m_setup.m_ptyData->ptyInputFlagsChangedHandler()(
|
||||
static_cast<Pty::PtyInputFlag>(m_inputFlags.toInt()));
|
||||
}
|
||||
|
||||
emit readyRead(m_ptyProcess->readAll(), {});
|
||||
});
|
||||
|
||||
@@ -430,6 +437,7 @@ public:
|
||||
|
||||
private:
|
||||
std::unique_ptr<IPtyProcess> m_ptyProcess;
|
||||
IPtyProcess::PtyInputFlags m_inputFlags;
|
||||
};
|
||||
|
||||
class QProcessImpl final : public DefaultImpl
|
||||
|
||||
@@ -18,12 +18,19 @@ namespace Internal { class ProcessPrivate; }
|
||||
|
||||
namespace Pty {
|
||||
|
||||
enum PtyInputFlag {
|
||||
None = 0x0,
|
||||
InputModeHidden = 0x1,
|
||||
};
|
||||
|
||||
using ResizeHandler = std::function<void(const QSize &)>;
|
||||
using PtyInputFlagsChangeHandler = std::function<void(PtyInputFlag)>;
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT SharedData
|
||||
{
|
||||
public:
|
||||
ResizeHandler m_handler;
|
||||
PtyInputFlagsChangeHandler m_inputFlagsChangedHandler;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT Data
|
||||
@@ -32,6 +39,15 @@ public:
|
||||
Data() : m_data(new SharedData) {}
|
||||
|
||||
void setResizeHandler(const ResizeHandler &handler) { m_data->m_handler = handler; }
|
||||
void setPtyInputFlagsChangedHandler(const PtyInputFlagsChangeHandler &handler)
|
||||
{
|
||||
m_data->m_inputFlagsChangedHandler = handler;
|
||||
}
|
||||
|
||||
PtyInputFlagsChangeHandler ptyInputFlagsChangedHandler() const
|
||||
{
|
||||
return m_data->m_inputFlagsChangedHandler;
|
||||
}
|
||||
|
||||
QSize size() const { return m_size; }
|
||||
void resize(const QSize &size);
|
||||
|
||||
@@ -126,7 +126,12 @@ void TerminalWidget::setupPty()
|
||||
env.unset("CLINK_NOAUTORUN");
|
||||
|
||||
m_process->setProcessMode(ProcessMode::Writer);
|
||||
m_process->setPtyData(Utils::Pty::Data());
|
||||
Utils::Pty::Data data;
|
||||
data.setPtyInputFlagsChangedHandler([this](Pty::PtyInputFlag flags) {
|
||||
const bool password = (flags & Pty::InputModeHidden);
|
||||
setPasswordMode(password);
|
||||
});
|
||||
m_process->setPtyData(data);
|
||||
m_process->setCommand(shellCommand);
|
||||
if (m_openParameters.workingDirectory.has_value())
|
||||
m_process->setWorkingDirectory(*m_openParameters.workingDirectory);
|
||||
|
||||
@@ -3716,6 +3716,31 @@
|
||||
id="use6090"
|
||||
transform="rotate(180,2008,576)" />
|
||||
</g>
|
||||
<g
|
||||
id="src/libs/solutions/terminal/images/passwordlock"
|
||||
transform="translate(-5,4)">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#transparentBackgroundRect"
|
||||
id="use1"
|
||||
transform="matrix(2.5,0,0,4,586,-1405)" />
|
||||
<path
|
||||
style="opacity:0.75;fill:#ffffff"
|
||||
d="m 582,423 v -5 c 0,-4 -4,-15 -16,-15 -12,-0.0312 -16,11 -16,15 0,4 0,5 0,5 h -4 v 36 h 40 v -36 z"
|
||||
id="path167"
|
||||
sodipodi:nodetypes="czzzcccccc" />
|
||||
<path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:4"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 566,407 c -6.624,0 -12,5.372 -12,12 v 12 h 4 v -12 c 0,-4.412 3.584,-8 8,-8 4.412,0 8,3.588 8,8 v 12 h 4 v -12 c 0,-6.628 -5.372,-12 -12,-12 z"
|
||||
id="lockbow-1" />
|
||||
<path
|
||||
style="display:inline;fill:#000000;fill-opacity:1"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 550,427 v 28 h 32 v -28 z m 18,15.388 V 447 h -4 v -4.612 c -1.172,-0.7 -2,-1.92 -2,-3.388 0,-2.212 1.792,-4 4,-4 2.208,0 4,1.788 4,4 0,1.464 -0.828,2.688 -2,3.388 z"
|
||||
id="lockbody-1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
|
||||
|
Before Width: | Height: | Size: 365 KiB After Width: | Height: | Size: 366 KiB |
Reference in New Issue
Block a user