mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-03-13 09:36:42 -04:00
Fix copy-to-clipboard shortcut on macOS
It turns out that the previous implementation, based on installing an event filter in every QAction instance, does not work on macOS, likely due to a Qt bug. Attempt to work around this by using a different implementation of the same idea, by reacting to ShortcutOverride events in the MainWindow object. Fixes #10929.
This commit is contained in:
parent
8bdbccf13f
commit
78cff4b6d9
@ -77,28 +77,6 @@
|
|||||||
#include "mainwindowadaptor.h"
|
#include "mainwindowadaptor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This filter gets installed on all the QAction objects within the MainWindow.
|
|
||||||
bool ActionEventFilter::eventFilter(QObject* watched, QEvent* event)
|
|
||||||
{
|
|
||||||
auto databaseWidget = getMainWindow()->m_ui->tabWidget->currentDatabaseWidget();
|
|
||||||
if (databaseWidget && event->type() == QEvent::Shortcut) {
|
|
||||||
// We check if we got a Shortcut event that uses the same key sequence as the
|
|
||||||
// OS default copy-to-clipboard shortcut.
|
|
||||||
static const auto stdCopyShortcuts = QKeySequence::keyBindings(QKeySequence::Copy);
|
|
||||||
if (stdCopyShortcuts.contains(static_cast<QShortcutEvent*>(event)->key())) {
|
|
||||||
// If so, we ask the database widget to check if any of its sub-widgets has text
|
|
||||||
// selected, and to copy it to the clipboard if that is the case. We do this
|
|
||||||
// because that is what the user likely expects to happen, yet Qt does not
|
|
||||||
// behave like that on all platforms.
|
|
||||||
if (databaseWidget->copyFocusedTextSelection()) {
|
|
||||||
// In that case, we return true to stop further processing of this event.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QObject::eventFilter(watched, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString MainWindow::BaseWindowTitle = "KeePassXC";
|
const QString MainWindow::BaseWindowTitle = "KeePassXC";
|
||||||
|
|
||||||
MainWindow* g_MainWindow = nullptr;
|
MainWindow* g_MainWindow = nullptr;
|
||||||
@ -472,9 +450,6 @@ MainWindow::MainWindow()
|
|||||||
m_ui->actionEntryRemovePasskey->setIcon(icons()->icon("document-close"));
|
m_ui->actionEntryRemovePasskey->setIcon(icons()->icon("document-close"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Handle copy to clipboard shortcut interference
|
|
||||||
m_ui->actionEntryCopyPassword->installEventFilter(&m_actionEventFilter);
|
|
||||||
|
|
||||||
m_actionMultiplexer.connect(
|
m_actionMultiplexer.connect(
|
||||||
SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode)));
|
SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode)));
|
||||||
m_actionMultiplexer.connect(SIGNAL(groupChanged()), this, SLOT(setMenuActionState()));
|
m_actionMultiplexer.connect(SIGNAL(groupChanged()), this, SLOT(setMenuActionState()));
|
||||||
@ -1409,6 +1384,33 @@ void MainWindow::databaseTabChanged(int tabIndex)
|
|||||||
updateEntryCountLabel();
|
updateEntryCountLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::event(QEvent* event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::ShortcutOverride) {
|
||||||
|
const auto keyevent = static_cast<QKeyEvent*>(event);
|
||||||
|
// Did we get a ShortcutOverride event with the same key sequence as the OS default
|
||||||
|
// copy-to-clipboard shortcut?
|
||||||
|
if (keyevent->matches(QKeySequence::Copy)) {
|
||||||
|
// If so, we ask the database widget to check if any of its sub-widgets has
|
||||||
|
// text selected, and to copy it to the clipboard if that is the case.
|
||||||
|
// We do this because that is what the user likely expects to happen, yet Qt does not
|
||||||
|
// behave like that (at least on some platforms).
|
||||||
|
auto dbWidget = m_ui->tabWidget->currentDatabaseWidget();
|
||||||
|
if (dbWidget && dbWidget->copyFocusedTextSelection()) {
|
||||||
|
// Note: instead of actively copying the selected text to the clipboard
|
||||||
|
// above, simply accepting the event would have a similar effect (Qt
|
||||||
|
// would deliver it as a key press to the current widget, which would
|
||||||
|
// trigger the built-in copy-to-clipboard behaviour). However, that
|
||||||
|
// would not come with our special (configurable) behaviour of
|
||||||
|
// clearing the clipboard after a certain time period.
|
||||||
|
keyevent->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QMainWindow::event(event);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::showEvent(QShowEvent* event)
|
void MainWindow::showEvent(QShowEvent* event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
@ -1494,7 +1496,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget::keyPressEvent(event);
|
QMainWindow::keyPressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::focusNextPrevChild(bool next)
|
bool MainWindow::focusNextPrevChild(bool next)
|
||||||
|
@ -39,14 +39,6 @@ class InactivityTimer;
|
|||||||
class SearchWidget;
|
class SearchWidget;
|
||||||
class MainWindowEventFilter;
|
class MainWindowEventFilter;
|
||||||
|
|
||||||
class ActionEventFilter : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -105,6 +97,7 @@ public slots:
|
|||||||
void restartApp(const QString& message);
|
void restartApp(const QString& message);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool event(QEvent* event) override;
|
||||||
void showEvent(QShowEvent* event) override;
|
void showEvent(QShowEvent* event) override;
|
||||||
void hideEvent(QHideEvent* event) override;
|
void hideEvent(QHideEvent* event) override;
|
||||||
void closeEvent(QCloseEvent* event) override;
|
void closeEvent(QCloseEvent* event) override;
|
||||||
@ -177,7 +170,6 @@ private:
|
|||||||
|
|
||||||
const QScopedPointer<Ui::MainWindow> m_ui;
|
const QScopedPointer<Ui::MainWindow> m_ui;
|
||||||
SignalMultiplexer m_actionMultiplexer;
|
SignalMultiplexer m_actionMultiplexer;
|
||||||
ActionEventFilter m_actionEventFilter;
|
|
||||||
QPointer<QAction> m_clearHistoryAction;
|
QPointer<QAction> m_clearHistoryAction;
|
||||||
QPointer<QAction> m_searchWidgetAction;
|
QPointer<QAction> m_searchWidgetAction;
|
||||||
QPointer<QMenu> m_entryContextMenu;
|
QPointer<QMenu> m_entryContextMenu;
|
||||||
@ -209,7 +201,6 @@ private:
|
|||||||
QTimer m_trayIconTriggerTimer;
|
QTimer m_trayIconTriggerTimer;
|
||||||
QSystemTrayIcon::ActivationReason m_trayIconTriggerReason;
|
QSystemTrayIcon::ActivationReason m_trayIconTriggerReason;
|
||||||
|
|
||||||
friend class ActionEventFilter;
|
|
||||||
friend class MainWindowEventFilter;
|
friend class MainWindowEventFilter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user