Implement Secure Input Field mode on macOS

* Fixes #4738
* Also fixes flaky handling of caps lock detection events
This commit is contained in:
Jonathan White 2025-01-04 09:38:02 -05:00
parent edab0faa94
commit 620abb96f2
9 changed files with 44 additions and 10 deletions

View File

@ -38,6 +38,7 @@ PasswordWidget::PasswordWidget(QWidget* parent)
{
m_ui->setupUi(this);
setFocusProxy(m_ui->passwordEdit);
m_ui->passwordEdit->installEventFilter(this);
const QIcon errorIcon = icons()->icon("dialog-error");
m_errorAction = m_ui->passwordEdit->addAction(errorIcon, QLineEdit::TrailingPosition);
@ -223,14 +224,19 @@ void PasswordWidget::updateRepeatStatus()
}
}
bool PasswordWidget::event(QEvent* event)
bool PasswordWidget::eventFilter(QObject* watched, QEvent* event)
{
if (isVisible()
&& (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease
|| event->type() == QEvent::FocusIn)) {
checkCapslockState();
if (watched == m_ui->passwordEdit) {
auto type = event->type();
if (isVisible() && (type == QEvent::KeyPress || type == QEvent::KeyRelease || type == QEvent::FocusIn)) {
checkCapslockState();
}
if (type == QEvent::FocusIn || type == QEvent::FocusOut) {
osUtils->setUserInputProtection(type == QEvent::FocusIn);
}
}
return QWidget::event(event);
// Continue with normal operations
return false;
}
void PasswordWidget::checkCapslockState()
@ -306,4 +312,4 @@ void PasswordWidget::updatePasswordStrength(const QString& password)
break;
}
}
}

View File

@ -44,6 +44,8 @@ public:
bool isPasswordVisible() const;
QString text();
bool eventFilter(QObject* watched, QEvent* event) override;
signals:
void textChanged(QString text);
@ -57,9 +59,6 @@ public slots:
void setEchoMode(QLineEdit::EchoMode mode);
void setClearButtonEnabled(bool enabled);
protected:
bool event(QEvent* event) override;
private slots:
void popupPasswordGenerator();
void updateRepeatStatus();

View File

@ -56,6 +56,11 @@ public:
*/
virtual bool isCapslockEnabled() = 0;
/**
* @param enable Toggle protection on user input (if available).
*/
virtual void setUserInputProtection(bool enable) = 0;
virtual void registerNativeEventFilter() = 0;
virtual bool registerGlobalShortcut(const QString& name,

View File

@ -150,6 +150,15 @@ bool MacUtils::isCapslockEnabled()
#endif
}
void MacUtils::setUserInputProtection(bool enable)
{
if (enable) {
EnableSecureEventInput();
} else {
DisableSecureEventInput();
}
}
/**
* Toggle application state between foreground app and UIElement app.
* Foreground apps have dock icons, UIElement apps do not.

View File

@ -40,6 +40,7 @@ public:
bool isLaunchAtStartupEnabled() const override;
void setLaunchAtStartup(bool enable) override;
bool isCapslockEnabled() override;
void setUserInputProtection(bool enable) override;
WId activeWindow();
bool raiseWindow(WId pid);

View File

@ -235,6 +235,12 @@ bool NixUtils::isCapslockEnabled()
return false;
}
void NixUtils::setUserInputProtection(bool enable)
{
// Linux does not support this feature
Q_UNUSED(enable)
}
void NixUtils::registerNativeEventFilter()
{
qApp->installNativeEventFilter(this);

View File

@ -35,6 +35,7 @@ public:
bool isLaunchAtStartupEnabled() const override;
void setLaunchAtStartup(bool enable) override;
bool isCapslockEnabled() override;
void setUserInputProtection(bool enable) override;
void registerNativeEventFilter() override;

View File

@ -136,6 +136,12 @@ bool WinUtils::isCapslockEnabled()
return GetKeyState(VK_CAPITAL) == 1;
}
void WinUtils::setUserInputProtection(bool enable)
{
// Windows does not support this feature
Q_UNUSED(enable)
}
bool WinUtils::isHighContrastMode() const
{
QSettings settings(R"(HKEY_CURRENT_USER\Control Panel\Accessibility\HighContrast)", QSettings::NativeFormat);

View File

@ -44,6 +44,7 @@ public:
bool isLaunchAtStartupEnabled() const override;
void setLaunchAtStartup(bool enable) override;
bool isCapslockEnabled() override;
void setUserInputProtection(bool enable) override;
bool isHighContrastMode() const;
void registerNativeEventFilter() override;