diff --git a/src/config/generalconf.cpp b/src/config/generalconf.cpp index 395ef30843..996a3d5e17 100644 --- a/src/config/generalconf.cpp +++ b/src/config/generalconf.cpp @@ -34,9 +34,7 @@ GeneralConf::GeneralConf(QWidget* parent) initScrollArea(); initAutostart(); -#if !defined(Q_OS_WIN) initAutoCloseIdleDaemon(); -#endif initShowTrayIcon(); initShowDesktopNotification(); initShowAbortNotification(); @@ -112,11 +110,7 @@ void GeneralConf::_updateComponents(bool allowEmptySavePath) m_squareMagnifier->setChecked(config.squareMagnifier()); m_saveLastRegion->setChecked(config.saveLastRegion()); m_reverseArrow->setChecked(config.reverseArrow()); - -#if !defined(Q_OS_WIN) m_autoCloseIdleDaemon->setChecked(config.autoCloseIdleDaemon()); -#endif - m_predefinedColorPaletteLarge->setChecked( config.predefinedColorPaletteLarge()); m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage()); @@ -127,9 +121,9 @@ void GeneralConf::_updateComponents(bool allowEmptySavePath) if (allowEmptySavePath || !config.savePath().isEmpty()) { m_savePath->setText(config.savePath()); } -#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) + m_showTray->setChecked(!config.disabledTrayIcon()); -#endif + #if !defined(Q_OS_MACOS) m_captureActiveMonitor->setChecked(config.captureActiveMonitor()); #endif @@ -335,7 +329,6 @@ void GeneralConf::initShowAbortNotification() void GeneralConf::initShowTrayIcon() { -#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) m_showTray = new QCheckBox(tr("Show tray icon"), this); m_showTray->setToolTip(tr("Show icon in the system tray")); m_scrollAreaLayout->addWidget(m_showTray); @@ -343,7 +336,6 @@ void GeneralConf::initShowTrayIcon() connect(m_showTray, &QCheckBox::clicked, this, [](bool checked) { ConfigHandler().setDisabledTrayIcon(!checked); }); -#endif } void GeneralConf::initHistoryConfirmationToDelete() diff --git a/src/core/flameshot.cpp b/src/core/flameshot.cpp index 8a29e31f2d..3d0385fa4e 100644 --- a/src/core/flameshot.cpp +++ b/src/core/flameshot.cpp @@ -8,6 +8,37 @@ #endif #if defined(Q_OS_MACOS) +#include +#include + +namespace { + +constexpr long NSApplicationActivationPolicyRegular = 0; +constexpr long NSApplicationActivationPolicyAccessory = 1; + +void setActivationPolicy(long policy) +{ + auto sharedApp = reinterpret_cast(objc_msgSend); + auto setPolicy = reinterpret_cast(objc_msgSend); + id nsApp = sharedApp(reinterpret_cast(objc_getClass("NSApplication")), + sel_registerName("sharedApplication")); + setPolicy(nsApp, sel_registerName("setActivationPolicy:"), policy); +} + +void setActivationPolicyRegular() +{ + setActivationPolicy(NSApplicationActivationPolicyRegular); +} + +void setActivationPolicyAccessory() +{ + setActivationPolicy(NSApplicationActivationPolicyAccessory); +} + +constexpr const char* visibleInDockProperty = "_visibleInDock"; + +} // namespace + #include #endif @@ -227,8 +258,7 @@ void Flameshot::launcher() } m_launcherWindow->show(); #if defined(Q_OS_MACOS) - m_launcherWindow->activateWindow(); - m_launcherWindow->raise(); + showDockIcon(m_launcherWindow); #endif } @@ -248,8 +278,7 @@ void Flameshot::config() position.moveCenter(currentScreen->availableGeometry().center()); m_configWindow->move(position.topLeft()); #if defined(Q_OS_MACOS) - m_configWindow->activateWindow(); - m_configWindow->raise(); + showDockIcon(m_configWindow); #endif } } @@ -259,8 +288,7 @@ void Flameshot::info() if (m_infoWindow == nullptr) { m_infoWindow = new InfoWindow(); #if defined(Q_OS_MACOS) - m_infoWindow->activateWindow(); - m_infoWindow->raise(); + showDockIcon(m_infoWindow); #endif } } @@ -286,9 +314,46 @@ void Flameshot::history() historyWidget->move(position.topLeft()); #if defined(Q_OS_MACOS) - historyWidget->activateWindow(); - historyWidget->raise(); + showDockIcon(historyWidget); +#endif +} #endif + +#if defined(Q_OS_MACOS) +void Flameshot::onWindowVisibilityChanged(QWindow::Visibility newVisibility) +{ + auto* qw = qobject_cast(sender()); + if (!qw) { + return; + } + + if (newVisibility == QWindow::Hidden) { + qw->setProperty(visibleInDockProperty, false); + --m_dockIconVisibleCount; + if (m_dockIconVisibleCount == 0) { + setActivationPolicyAccessory(); + } + } else { + bool windowTrackedInDock = qw->property(visibleInDockProperty).toBool(); + if (!windowTrackedInDock) { + qw->setProperty(visibleInDockProperty, true); + ++m_dockIconVisibleCount; + setActivationPolicyRegular(); + } + } +} + +void Flameshot::showDockIcon(QWidget* w) +{ + QWindow* qw = w->windowHandle(); + if (!qw) { + return; + } + + connect(qw, + &QWindow::visibilityChanged, + this, + &Flameshot::onWindowVisibilityChanged); } #endif diff --git a/src/core/flameshot.h b/src/core/flameshot.h index bc97080560..6373f10eab 100644 --- a/src/core/flameshot.h +++ b/src/core/flameshot.h @@ -8,11 +8,13 @@ #include #include #include +#include class CaptureWidget; class ConfigWindow; class InfoWindow; class CaptureLauncher; +class QWidget; #ifdef ENABLE_IMGUR class UploadHistory; #endif @@ -91,6 +93,15 @@ public slots: QPointer m_launcherWindow; QPointer m_configWindow; +#if defined(Q_OS_MACOS) +public: + void showDockIcon(QWidget* window); + +private: + void onWindowVisibilityChanged(QWindow::Visibility newVisibility); + int m_dockIconVisibleCount = 0; +#endif + #if (defined(Q_OS_MACOS) || defined(Q_OS_WIN)) QHotkey* m_HotkeyScreenshotCapture; #endif diff --git a/src/core/flameshotdaemon.cpp b/src/core/flameshotdaemon.cpp index 8c7852e2aa..298f00041c 100644 --- a/src/core/flameshotdaemon.cpp +++ b/src/core/flameshotdaemon.cpp @@ -51,9 +51,7 @@ * quits. * * If the `autoCloseIdleDaemon` option is true, the daemon will close as soon as - * it is not needed to host pinned screenshots and the clipboard. On Windows, - * this option is disabled and the daemon always persists, because the system - * tray is currently the only way to interact with flameshot there. + * it is not needed to host pinned screenshots and the clipboard. * * Both the daemon and non-daemon flameshot processes use the same public API, * which is implemented as static methods. In the daemon process, this class is @@ -85,9 +83,7 @@ FlameshotDaemon::FlameshotDaemon() m_hostingClipboard = false; quitIfIdle(); }); -#ifdef Q_OS_WIN - m_persist = true; -#else + m_persist = !ConfigHandler().autoCloseIdleDaemon(); connect(ConfigHandler::getInstance(), &ConfigHandler::fileChanged, @@ -97,7 +93,6 @@ FlameshotDaemon::FlameshotDaemon() enableTrayIcon(!config.disabledTrayIcon()); m_persist = !config.autoCloseIdleDaemon(); }); -#endif #if !defined(DISABLE_UPDATE_CHECKER) if (ConfigHandler().checkForUpdates()) { @@ -371,13 +366,10 @@ void FlameshotDaemon::attachTextToClipboard(const QString& text, void FlameshotDaemon::initTrayIcon() { -#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) if (!ConfigHandler().disabledTrayIcon()) { enableTrayIcon(true); } -#elif defined(Q_OS_WIN) - enableTrayIcon(true); - +#if defined(Q_OS_WIN) GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this); qApp->installNativeEventFilter(nativeFilter); #endif diff --git a/src/utils/confighandler.cpp b/src/utils/confighandler.cpp index d57ceebf7e..66fbb1bee0 100644 --- a/src/utils/confighandler.cpp +++ b/src/utils/confighandler.cpp @@ -86,9 +86,7 @@ static QMap> OPTION("allowMultipleGuiInstances" ,Bool ( false )), OPTION("showMagnifier" ,Bool ( false )), OPTION("squareMagnifier" ,Bool ( false )), -#if !defined(Q_OS_WIN) OPTION("autoCloseIdleDaemon" ,Bool ( false )), -#endif OPTION("startupLaunch" ,Bool ( false )), OPTION("showStartupLaunchMessage" ,Bool ( true )), OPTION("showQuitPrompt" ,Bool ( false )),