diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 4d7bc96bb..fa200ddb8 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -542,14 +542,155 @@ uint djbStringHash(const std::string &string) { class MainWindow::Private { public: + explicit Private(not_null window) + : _public(window) { + } + #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION Glib::RefPtr dbusConnection; + + StatusNotifierItem *sniTrayIcon = nullptr; + uint sniRegisteredSignalId = 0; + uint sniWatcherId = 0; + std::unique_ptr trayIconFile; + + void setSNITrayIcon(int counter, bool muted); + void attachToSNITrayIcon(); + void handleSNIHostRegistered(); + + void handleSNIOwnerChanged( + const QString &service, + const QString &oldOwner, + const QString &newOwner); #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION + +private: + not_null _public; }; +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION +void MainWindow::Private::setSNITrayIcon(int counter, bool muted) { + const auto iconName = GetTrayIconName(counter, muted); + const auto panelIconName = GetPanelIconName(counter, muted); + + if (iconName == panelIconName) { + if (sniTrayIcon->iconName() == iconName) { + return; + } + + sniTrayIcon->setIconByName(iconName); + sniTrayIcon->setToolTipIconByName(iconName); + } else if (IsIndicatorApplication()) { + if (!IsIconRegenerationNeeded(counter, muted) + && trayIconFile + && sniTrayIcon->iconName() == trayIconFile->fileName()) { + return; + } + + const auto icon = TrayIconGen(counter, muted); + trayIconFile = TrayIconFile(icon, _public); + + if (trayIconFile) { + // indicator-application doesn't support tooltips + sniTrayIcon->setIconByName(trayIconFile->fileName()); + } + } else { + if (!IsIconRegenerationNeeded(counter, muted) + && !sniTrayIcon->iconPixmap().isEmpty() + && sniTrayIcon->iconName().isEmpty()) { + return; + } + + const auto icon = TrayIconGen(counter, muted); + sniTrayIcon->setIconByPixmap(icon); + sniTrayIcon->setToolTipIconByPixmap(icon); + } +} + +void MainWindow::Private::attachToSNITrayIcon() { + sniTrayIcon->setToolTipTitle(AppName.utf16()); + connect(sniTrayIcon, + &StatusNotifierItem::activateRequested, + [=](const QPoint &) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + _public->handleTrayIconActication(QSystemTrayIcon::Trigger); + }); + }); + connect(sniTrayIcon, + &StatusNotifierItem::secondaryActivateRequested, + [=](const QPoint &) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + _public->handleTrayIconActication(QSystemTrayIcon::MiddleClick); + }); + }); +} + +void MainWindow::Private::handleSNIHostRegistered() { + if (_public->_sniAvailable) { + return; + } + + _public->_sniAvailable = true; + + if (Core::App().settings().workMode() == WorkMode::WindowOnly) { + return; + } + + LOG(("Switching to SNI tray icon...")); + + if (_public->trayIcon) { + _public->trayIcon->setContextMenu(nullptr); + _public->trayIcon->deleteLater(); + } + _public->trayIcon = nullptr; + + _public->psSetupTrayIcon(); + + SkipTaskbar( + _public->windowHandle(), + Core::App().settings().workMode() == WorkMode::TrayOnly); +} + +void MainWindow::Private::handleSNIOwnerChanged( + const QString &service, + const QString &oldOwner, + const QString &newOwner) { + _public->_sniAvailable = IsSNIAvailable(); + + if (Core::App().settings().workMode() == WorkMode::WindowOnly) { + return; + } + + if (oldOwner.isEmpty() && !newOwner.isEmpty() && _public->_sniAvailable) { + LOG(("Switching to SNI tray icon...")); + } else if (!oldOwner.isEmpty() && newOwner.isEmpty()) { + LOG(("Switching to Qt tray icon...")); + } else { + return; + } + + if (_public->trayIcon) { + _public->trayIcon->setContextMenu(0); + _public->trayIcon->deleteLater(); + } + _public->trayIcon = nullptr; + + if (_public->trayAvailable()) { + _public->psSetupTrayIcon(); + } else { + LOG(("System tray is not available.")); + } + + SkipTaskbar( + _public->windowHandle(), + (Core::App().settings().workMode() == WorkMode::TrayOnly) + && _public->trayAvailable()); +} +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION + MainWindow::MainWindow(not_null controller) : Window::MainWindow(controller) -, _private(std::make_unique()) { +, _private(std::make_unique(this)) { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION qDBusRegisterMetaType(); qDBusRegisterMetaType(); @@ -586,7 +727,7 @@ void MainWindow::initHook() { _private->dbusConnection = Gio::DBus::Connection::get_sync( Gio::DBus::BusType::BUS_TYPE_SESSION); - _sniRegisteredSignalId = _private->dbusConnection->signal_subscribe( + _private->sniRegisteredSignalId = _private->dbusConnection->signal_subscribe( []( const Glib::RefPtr &connection, const Glib::ustring &sender_name, @@ -597,7 +738,7 @@ void MainWindow::initHook() { if (signal_name == "StatusNotifierHostRegistered") { crl::on_main([] { if (const auto window = App::wnd()) { - window->handleSNIHostRegistered(); + window->_private->handleSNIHostRegistered(); } }); } @@ -607,14 +748,14 @@ void MainWindow::initHook() { "StatusNotifierHostRegistered", std::string(kSNIWatcherObjectPath)); - _sniWatcherId = base::Platform::DBus::RegisterServiceWatcher( + _private->sniWatcherId = base::Platform::DBus::RegisterServiceWatcher( _private->dbusConnection, std::string(kSNIWatcherService), [=]( const Glib::ustring &service, const Glib::ustring &oldOwner, const Glib::ustring &newOwner) { - handleSNIOwnerChanged( + _private->handleSNIOwnerChanged( QString::fromStdString(service), QString::fromStdString(oldOwner), QString::fromStdString(newOwner)); @@ -638,7 +779,7 @@ void MainWindow::initHook() { bool MainWindow::hasTrayIcon() const { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION - return trayIcon || (_sniAvailable && _sniTrayIcon); + return trayIcon || (_sniAvailable && _private->sniTrayIcon); #else return trayIcon; #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION @@ -656,128 +797,6 @@ void MainWindow::psShowTrayMenu() { void MainWindow::psTrayMenuUpdated() { } -#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION -void MainWindow::setSNITrayIcon(int counter, bool muted) { - const auto iconName = GetTrayIconName(counter, muted); - const auto panelIconName = GetPanelIconName(counter, muted); - - if (iconName == panelIconName) { - if (_sniTrayIcon->iconName() == iconName) { - return; - } - - _sniTrayIcon->setIconByName(iconName); - _sniTrayIcon->setToolTipIconByName(iconName); - } else if (IsIndicatorApplication()) { - if (!IsIconRegenerationNeeded(counter, muted) - && _trayIconFile - && _sniTrayIcon->iconName() == _trayIconFile->fileName()) { - return; - } - - const auto icon = TrayIconGen(counter, muted); - _trayIconFile = TrayIconFile(icon, this); - - if (_trayIconFile) { - // indicator-application doesn't support tooltips - _sniTrayIcon->setIconByName(_trayIconFile->fileName()); - } - } else { - if (!IsIconRegenerationNeeded(counter, muted) - && !_sniTrayIcon->iconPixmap().isEmpty() - && _sniTrayIcon->iconName().isEmpty()) { - return; - } - - const auto icon = TrayIconGen(counter, muted); - _sniTrayIcon->setIconByPixmap(icon); - _sniTrayIcon->setToolTipIconByPixmap(icon); - } -} - -void MainWindow::attachToSNITrayIcon() { - _sniTrayIcon->setToolTipTitle(AppName.utf16()); - connect(_sniTrayIcon, - &StatusNotifierItem::activateRequested, - this, - [=](const QPoint &) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - handleTrayIconActication(QSystemTrayIcon::Trigger); - }); - }); - connect(_sniTrayIcon, - &StatusNotifierItem::secondaryActivateRequested, - this, - [=](const QPoint &) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - handleTrayIconActication(QSystemTrayIcon::MiddleClick); - }); - }); -} - -void MainWindow::handleSNIHostRegistered() { - if (_sniAvailable) { - return; - } - - _sniAvailable = true; - - if (Core::App().settings().workMode() == WorkMode::WindowOnly) { - return; - } - - LOG(("Switching to SNI tray icon...")); - - if (trayIcon) { - trayIcon->setContextMenu(nullptr); - trayIcon->deleteLater(); - } - trayIcon = nullptr; - - psSetupTrayIcon(); - - SkipTaskbar( - windowHandle(), - Core::App().settings().workMode() == WorkMode::TrayOnly); -} - -void MainWindow::handleSNIOwnerChanged( - const QString &service, - const QString &oldOwner, - const QString &newOwner) { - _sniAvailable = IsSNIAvailable(); - - if (Core::App().settings().workMode() == WorkMode::WindowOnly) { - return; - } - - if (oldOwner.isEmpty() && !newOwner.isEmpty() && _sniAvailable) { - LOG(("Switching to SNI tray icon...")); - } else if (!oldOwner.isEmpty() && newOwner.isEmpty()) { - LOG(("Switching to Qt tray icon...")); - } else { - return; - } - - if (trayIcon) { - trayIcon->setContextMenu(0); - trayIcon->deleteLater(); - } - trayIcon = nullptr; - - if (trayAvailable()) { - psSetupTrayIcon(); - } else { - LOG(("System tray is not available.")); - } - - SkipTaskbar( - windowHandle(), - (Core::App().settings().workMode() == WorkMode::TrayOnly) - && trayAvailable()); -} -#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION - void MainWindow::psSetupTrayIcon() { const auto counter = Core::App().unreadBadge(); const auto muted = Core::App().unreadBadgeMuted(); @@ -785,16 +804,16 @@ void MainWindow::psSetupTrayIcon() { if (_sniAvailable) { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION LOG(("Using SNI tray icon.")); - if (!_sniTrayIcon) { - _sniTrayIcon = new StatusNotifierItem( + if (!_private->sniTrayIcon) { + _private->sniTrayIcon = new StatusNotifierItem( QCoreApplication::applicationName(), this); - _sniTrayIcon->setTitle(AppName.utf16()); - _sniTrayIcon->setContextMenu(trayIconMenu); - setSNITrayIcon(counter, muted); + _private->sniTrayIcon->setTitle(AppName.utf16()); + _private->sniTrayIcon->setContextMenu(trayIconMenu); + _private->setSNITrayIcon(counter, muted); - attachToSNITrayIcon(); + _private->attachToSNITrayIcon(); } updateIconCounters(); #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION @@ -817,11 +836,11 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { return; } else if (mode == WorkMode::WindowOnly) { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION - if (_sniTrayIcon) { - _sniTrayIcon->setContextMenu(0); - _sniTrayIcon->deleteLater(); + if (_private->sniTrayIcon) { + _private->sniTrayIcon->setContextMenu(0); + _private->sniTrayIcon->deleteLater(); } - _sniTrayIcon = nullptr; + _private->sniTrayIcon = nullptr; #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (trayIcon) { @@ -885,8 +904,8 @@ void MainWindow::updateIconCounters() { } } - if (_sniTrayIcon) { - setSNITrayIcon(counter, muted); + if (_private->sniTrayIcon) { + _private->setSNITrayIcon(counter, muted); } #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION @@ -1215,18 +1234,16 @@ void MainWindow::handleNativeSurfaceChanged(bool exist) { MainWindow::~MainWindow() { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (_private->dbusConnection) { - if (_sniRegisteredSignalId != 0) { + if (_private->sniRegisteredSignalId != 0) { _private->dbusConnection->signal_unsubscribe( - _sniRegisteredSignalId); + _private->sniRegisteredSignalId); } - if (_sniWatcherId != 0) { + if (_private->sniWatcherId != 0) { _private->dbusConnection->signal_unsubscribe( - _sniWatcherId); + _private->sniWatcherId); } } - - delete _sniTrayIcon; #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 9700c595a..ebdf560e6 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -16,11 +16,6 @@ namespace Ui { class PopupMenu; } // namespace Ui -#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION -class QTemporaryFile; -class StatusNotifierItem; -#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION - namespace Platform { class MainWindow : public Window::MainWindow { @@ -71,7 +66,9 @@ protected: private: class Private; + friend class Private; const std::unique_ptr _private; + bool _sniAvailable = false; base::unique_qptr _trayIconMenuXEmbed; @@ -114,22 +111,6 @@ private: void psLinuxMonospace(); void psLinuxClearFormat(); -#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION - StatusNotifierItem *_sniTrayIcon = nullptr; - uint _sniRegisteredSignalId = 0; - uint _sniWatcherId = 0; - std::unique_ptr _trayIconFile; - - void setSNITrayIcon(int counter, bool muted); - void attachToSNITrayIcon(); - void handleSNIHostRegistered(); - - void handleSNIOwnerChanged( - const QString &service, - const QString &oldOwner, - const QString &newOwner); -#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION - }; } // namespace Platform