diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 5d4ee8fe..92bca7a8 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -52,6 +52,7 @@ #include #endif +static const int systemTrayWaitTime = 10000; static const QString allFilesFilter(QObject::tr("All files (*.*)")); #if defined(Q_OS_WIN) static const char barrierConfigName[] = "barrier.sgc"; @@ -156,6 +157,9 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pComboServerList->hide(); m_pLabelPadlock->hide(); + m_OpenHiddenTrayTimer.setSingleShot(true); + connect(&m_OpenHiddenTrayTimer, &QTimer::timeout, this, &MainWindow::on_m_OpenHiddenTrayTimer_triggered); + updateSSLFingerprint(); // resize window to smallest reasonable size @@ -190,6 +194,28 @@ void MainWindow::open() if (appConfig().getAutoHide()) { hide(); + + // If system tray is not available, start a timer to ensure we don't become + // stuck in a hidden state + // + // The previous solution for this would wait at the startup of the app to + // see if the system tray becomes available before showing any window - even + // if the user didn't have autohide enabled. + // + // This solution instead, hides the window if they have autohide enabled, or shows + // the window if they don't. Then if the user has selected to autohide the window + // it checks after a period of time if the system tray is not available - if it + // isn't then it forces the window to show. + // + // This provides a much better UX for the two main use cases (user starting app with + // autohide enabled with system tray available and user starting app with autohide + // disabled with no system tray available). And provides a workaround for the edge + // case of a user enabling autohide with no system tray available (this should now + // be harder to do as the option in settings will become disabled). + if (!QSystemTrayIcon::isSystemTrayAvailable()) + { + m_OpenHiddenTrayTimer.start(systemTrayWaitTime); + } } else { showNormal(); } @@ -208,6 +234,18 @@ void MainWindow::open() } } +void MainWindow::on_m_OpenHiddenTrayTimer_triggered() +{ + // If the system tray is still not available then force window to show + if (!QSystemTrayIcon::isSystemTrayAvailable()) + { + fprintf(stdout, "System tray not available, force disabling auto hide!\n"); + m_AppConfig->setAutoHide(false); + + showNormal(); + } +} + void MainWindow::setStatus(const QString &status) { m_pStatusLabel->setText(status); @@ -1277,7 +1315,8 @@ void MainWindow::bonjourInstallFinished() void MainWindow::windowStateChanged() { - if (windowState() == Qt::WindowMinimized && appConfig().getMinimizeToTray()) + // If we are minimising and minimise to tray is enabled and system tray is available then hide the window + if (windowState() == Qt::WindowMinimized && appConfig().getMinimizeToTray() && QSystemTrayIcon::isSystemTrayAvailable()) hide(); } diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 131b31ce..f42776c7 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "ui_MainWindowBase.h" @@ -201,11 +202,13 @@ public slots: SslCertificate* m_pSslCertificate; QStringList m_PendingClientNames; LogWindow *m_pLogWindow; + QTimer m_OpenHiddenTrayTimer; private slots: void on_m_pCheckBoxAutoConfig_toggled(bool checked); void on_m_pComboServerList_currentIndexChanged(QString ); void on_m_pButtonReload_clicked(); + void on_m_OpenHiddenTrayTimer_triggered(); void installBonjour(); }; diff --git a/src/gui/src/QBarrierApplication.cpp b/src/gui/src/QBarrierApplication.cpp index f9362c74..7a6ec970 100644 --- a/src/gui/src/QBarrierApplication.cpp +++ b/src/gui/src/QBarrierApplication.cpp @@ -29,6 +29,12 @@ QBarrierApplication::QBarrierApplication(int& argc, char** argv) : m_Translator(NULL) { s_Instance = this; + + // By default do not quit when the last window is closed as we minimise + // to the system tray, but listen for the lastWindow closing so that + // if the system tray is not available we can quit. + setQuitOnLastWindowClosed(false); + connect(this, &QApplication::lastWindowClosed, this, &QBarrierApplication::onLastWindowClosed); } QBarrierApplication::~QBarrierApplication() @@ -69,3 +75,12 @@ void QBarrierApplication::setTranslator(QTranslator* translator) m_Translator = translator; installTranslator(m_Translator); } + +void QBarrierApplication::onLastWindowClosed() +{ + // If there is no system tray available then quit when the last window is closed + if (!QSystemTrayIcon::isSystemTrayAvailable()) + { + quit(); + } +} diff --git a/src/gui/src/QBarrierApplication.h b/src/gui/src/QBarrierApplication.h index bd348b3a..107cd3ba 100644 --- a/src/gui/src/QBarrierApplication.h +++ b/src/gui/src/QBarrierApplication.h @@ -37,6 +37,9 @@ class QBarrierApplication : public QApplication static QBarrierApplication* getInstance(); + private Q_SLOTS: + void onLastWindowClosed(); + private: QTranslator* m_Translator; diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 1caeae5d..37c34714 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -52,6 +52,10 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); + // Don't allow auto hide or minimise to tray if it's not available + m_pCheckBoxAutoHide->setEnabled(QSystemTrayIcon::isSystemTrayAvailable()); + m_pCheckBoxMinimizeToTray->setEnabled(QSystemTrayIcon::isSystemTrayAvailable()); + #if defined(Q_OS_WIN) m_pComboElevate->setCurrentIndex(static_cast(appConfig().elevateMode())); #else diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 73251d52..498c2100 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -16,9 +16,6 @@ * along with this program. If not, see . */ -#define TRAY_RETRY_COUNT 5 -#define TRAY_RETRY_WAIT 2000 - #include "QBarrierApplication.h" #include "MainWindow.h" #include "AppConfig.h" @@ -47,8 +44,6 @@ public: } }; -int waitForTray(); - #if defined(Q_OS_MAC) bool checkMacAssistiveDevices(); #endif @@ -93,20 +88,9 @@ int main(int argc, char* argv[]) } #endif - int trayAvailable = waitForTray(); - - QApplication::setQuitOnLastWindowClosed(false); - QSettings settings; AppConfig appConfig (&settings); - if (appConfig.getAutoHide() && !trayAvailable) - { - // force auto hide to false - otherwise there is no way to get the GUI back - fprintf(stdout, "System tray not available, force disabling auto hide!\n"); - appConfig.setAutoHide(false); - } - app.switchTranslator(appConfig.language()); MainWindow mainWindow(settings, appConfig); @@ -124,29 +108,6 @@ int main(int argc, char* argv[]) return app.exec(); } -int waitForTray() -{ - // on linux, the system tray may not be available immediately after logging in, - // so keep retrying but give up after a short time. - int trayAttempts = 0; - while (true) - { - if (QSystemTrayIcon::isSystemTrayAvailable()) - { - break; - } - - if (++trayAttempts > TRAY_RETRY_COUNT) - { - fprintf(stdout, "System tray is unavailable.\n"); - return false; - } - - QThreadImpl::msleep(TRAY_RETRY_WAIT); - } - return true; -} - #if defined(Q_OS_MAC) bool checkMacAssistiveDevices() {