diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index f14d1425bdf1c..c4039272b0c3f 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -241,6 +241,7 @@ set(client_SRCS tray/asyncimageresponse.cpp tray/trayimageprovider.cpp tray/trayaccountmenupolicy.h + tray/trayactivationpolicy.h tray/trayaccountappsmodel.h tray/trayaccountappsmodel.cpp tray/usermodel.h diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 6e6f60619e625..c92332711def8 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -34,6 +34,7 @@ #include "filedetails/sortedsharemodel.h" #include "activity/sortedactivitylistmodel.h" #include "activity/syncstatussummary.h" +#include "tray/trayactivationpolicy.h" #include "tray/trayaccountappsmodel.h" #include "search/unifiedsearchresultslistmodel.h" #include "integration/fileactionsmodel.h" @@ -244,7 +245,7 @@ void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason) const auto currentUser = UserModel::instance()->currentUser(); if (reason == QSystemTrayIcon::DoubleClick && currentUser && currentUser->hasLocalFolder()) { currentUser->openLocalFolder(); - } else if (reason == QSystemTrayIcon::Trigger) { + } else if (TrayActivationPolicy::opensPrimaryPopup(reason)) { if (AccountManager::instance()->accounts().isEmpty()) { // Without a configured account the tray icon drives the setup wizard // directly: open it, or bring the existing one back to front instead diff --git a/src/gui/tray/trayactivationpolicy.h b/src/gui/tray/trayactivationpolicy.h new file mode 100644 index 0000000000000..f9d796289f06e --- /dev/null +++ b/src/gui/tray/trayactivationpolicy.h @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include + +namespace OCC { + +/** @brief Defines which tray-icon activations open the primary tray popup. */ +class TrayActivationPolicy +{ +public: + /** @brief Whether the activation should open or toggle the primary tray popup. */ + [[nodiscard]] static constexpr bool opensPrimaryPopup(const QSystemTrayIcon::ActivationReason reason) + { + if (reason == QSystemTrayIcon::Trigger) { + return true; + } + +#ifdef Q_OS_MACOS + return reason == QSystemTrayIcon::Context; +#else + return false; +#endif + } +}; + +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e04a968cc79d9..1f2e35cd7d844 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -102,6 +102,7 @@ nextcloud_add_test(IconUtils) nextcloud_add_test(NotificationSoundPlayer) nextcloud_add_test(SetUserStatusDialog) nextcloud_add_test(TrayAccountMenuPolicy) +nextcloud_add_test(TrayActivationPolicy) nextcloud_add_test(UnifiedSearchListmodel) nextcloud_add_test(ActivityListModel) nextcloud_add_test(SortedActivityListModel) diff --git a/test/testtrayactivationpolicy.cpp b/test/testtrayactivationpolicy.cpp new file mode 100644 index 0000000000000..7931aceb4a06d --- /dev/null +++ b/test/testtrayactivationpolicy.cpp @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: CC0-1.0 + * + * This software is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + */ + +#include "tray/trayactivationpolicy.h" + +#include + +using namespace OCC; + +class TestTrayActivationPolicy : public QObject +{ + Q_OBJECT + +private slots: + void testPrimaryClickOpensPopup() + { + QVERIFY(TrayActivationPolicy::opensPrimaryPopup(QSystemTrayIcon::Trigger)); + } + + void testContextClickBehaviorIsPlatformSpecific() + { +#ifdef Q_OS_MACOS + QVERIFY(TrayActivationPolicy::opensPrimaryPopup(QSystemTrayIcon::Context)); +#else + QVERIFY(!TrayActivationPolicy::opensPrimaryPopup(QSystemTrayIcon::Context)); +#endif + } + + void testOtherActivationsDoNotOpenPopup() + { + QVERIFY(!TrayActivationPolicy::opensPrimaryPopup(QSystemTrayIcon::Unknown)); + QVERIFY(!TrayActivationPolicy::opensPrimaryPopup(QSystemTrayIcon::DoubleClick)); + QVERIFY(!TrayActivationPolicy::opensPrimaryPopup(QSystemTrayIcon::MiddleClick)); + } +}; + +QTEST_APPLESS_MAIN(TestTrayActivationPolicy) +#include "testtrayactivationpolicy.moc"