diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 96475a0fb..e5f5ea613 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -139,6 +139,7 @@ MainWindow::MainWindow() , m_trayIcon(nullptr) , m_appExitCalled(false) , m_appExiting(false) + , m_lastFocusOutTime(0) { g_MainWindow = this; @@ -403,6 +404,12 @@ MainWindow::MainWindow() connect(m_screenLockListener, SIGNAL(screenLocked()), SLOT(handleScreenLock())); #endif + // Tray Icon setup + connect(Application::instance(), SIGNAL(focusWindowChanged(QWindow*)), SLOT(focusWindowChanged(QWindow*))); + m_trayIconTriggerReason = QSystemTrayIcon::Unknown; + m_trayIconTriggerTimer.setSingleShot(true); + connect(&m_trayIconTriggerTimer, SIGNAL(timeout()), SLOT(processTrayIconTrigger())); + updateTrayIcon(); if (config()->hasAccessError()) { @@ -919,7 +926,7 @@ bool MainWindow::saveLastDatabases() } QStringList openDatabases; - for (int i=0; i < m_ui->tabWidget->count(); ++i) { + for (int i = 0; i < m_ui->tabWidget->count(); ++i) { auto dbWidget = m_ui->tabWidget->databaseWidgetFromIndex(i); openDatabases.append(dbWidget->database()->filePath()); } @@ -1038,10 +1045,38 @@ void MainWindow::applySettingsChanges() updateTrayIcon(); } +void MainWindow::focusWindowChanged(QWindow* focusWindow) +{ + if (focusWindow != windowHandle()) { + m_lastFocusOutTime = Clock::currentSecondsSinceEpoch(); + } +} + void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason) { - if (reason == QSystemTrayIcon::Trigger || reason == QSystemTrayIcon::MiddleClick) { + if (!m_trayIconTriggerTimer.isActive()) { + m_trayIconTriggerTimer.start(150); + } + // Overcome Qt bug https://bugreports.qt.io/browse/QTBUG-69698 + // Store last issued tray icon activation reason to properly + // capture doubleclick events + m_trayIconTriggerReason = reason; +} + +void MainWindow::processTrayIconTrigger() +{ + if (m_trayIconTriggerReason == QSystemTrayIcon::DoubleClick) { + // Always toggle window on double click toggleWindow(); + } else if (m_trayIconTriggerReason == QSystemTrayIcon::Trigger + || m_trayIconTriggerReason == QSystemTrayIcon::MiddleClick) { + // On single/middle click focus the window if it is not hidden + // and did not have focus less than a second ago, otherwise toggle + if (isHidden() || (Clock::currentSecondsSinceEpoch() - m_lastFocusOutTime) <= 1) { + toggleWindow(); + } else { + bringToFront(); + } } } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 5a72d6f02..f1e543468 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -85,6 +85,7 @@ private slots: void showAboutDialog(); void showUpdateCheckStartup(); void showUpdateCheckDialog(); + void focusWindowChanged(QWindow* focusWindow); void hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested); void openDonateUrl(); void openBugReportUrl(); @@ -107,6 +108,7 @@ private slots: void showGroupContextMenu(const QPoint& globalPos); void applySettingsChanges(); void trayIconTriggered(QSystemTrayIcon::ActivationReason reason); + void processTrayIconTrigger(); void lockDatabasesAfterInactivity(); void forgetTouchIDAfterInactivity(); void handleScreenLock(); @@ -146,6 +148,9 @@ private: bool m_appExitCalled; bool m_appExiting; + uint m_lastFocusOutTime; + QTimer m_trayIconTriggerTimer; + QSystemTrayIcon::ActivationReason m_trayIconTriggerReason; }; /** diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 63e36fbaa..0db2a5dfb 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -1286,11 +1286,11 @@ void TestGui::testTrayRestoreHide() QSKIP("QSystemTrayIcon::isSystemTrayAvailable() = false, skipping tray restore/hide test..."); } + m_mainWindow->hideWindow(); + QVERIFY(!m_mainWindow->isVisible()); + auto* trayIcon = m_mainWindow->findChild(); - QVERIFY(m_mainWindow->isVisible()); - - trayIcon->activated(QSystemTrayIcon::Trigger); - QTRY_VERIFY(!m_mainWindow->isVisible()); + QVERIFY(trayIcon); trayIcon->activated(QSystemTrayIcon::Trigger); QTRY_VERIFY(m_mainWindow->isVisible()); @@ -1298,8 +1298,17 @@ void TestGui::testTrayRestoreHide() trayIcon->activated(QSystemTrayIcon::Trigger); QTRY_VERIFY(!m_mainWindow->isVisible()); - trayIcon->activated(QSystemTrayIcon::Trigger); + trayIcon->activated(QSystemTrayIcon::MiddleClick); QTRY_VERIFY(m_mainWindow->isVisible()); + + trayIcon->activated(QSystemTrayIcon::MiddleClick); + QTRY_VERIFY(!m_mainWindow->isVisible()); + + trayIcon->activated(QSystemTrayIcon::DoubleClick); + QTRY_VERIFY(m_mainWindow->isVisible()); + + trayIcon->activated(QSystemTrayIcon::DoubleClick); + QTRY_VERIFY(!m_mainWindow->isVisible()); } int TestGui::addCannedEntries()